diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java new file mode 100644 index 0000000000..c5f64c4383 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/permissioning/NodeSmartContractPermissioningOutOfSyncAcceptanceTest.java @@ -0,0 +1,76 @@ +/* + * 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.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; + +public class NodeSmartContractPermissioningOutOfSyncAcceptanceTest + extends NodeSmartContractPermissioningAcceptanceTestBase { + private Node bootnode; + private Node permissionedNodeA; + private Node permissionedNodeB; + + @Before + public void setUp() throws InterruptedException { + bootnode = bootnode("bootnode"); + permissionedNodeA = permissionedNode("permissioned-node-A"); + permissionedNodeB = permissionedNode("permissioned-node-B"); + + permissionedCluster.start(bootnode, permissionedNodeA); + + // update onchain smart contract to whitelist nodes + permissionedNodeA.execute(allowNode(bootnode)); + permissionedNodeA.verify(nodeIsAllowed(bootnode)); + permissionedNodeA.execute(allowNode(permissionedNodeA)); + permissionedNodeA.verify(nodeIsAllowed(permissionedNodeA)); + permissionedNodeA.verify(admin.addPeer(bootnode)); + } + + @Test + public void addNodeToClusterAndVerifyNonBootNodePeerConnectionWorksAfterSync() { + final long blockchainHeight = 50L; + WaitUtils.waitFor( + 120, + () -> + assertThat(currentHeight(permissionedNodeA)) + .isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight))); + + // Add Node B + permissionedCluster.addNode(permissionedNodeB); + permissionedNodeA.execute(allowNode(permissionedNodeB)); + permissionedNodeA.verify(admin.addPeer(permissionedNodeB)); + + // check that connection is forbidden (while node b is syncing) + permissionedNodeB.verify(connectionIsForbidden(permissionedNodeA, permissionedNodeB)); + + // connection should be allowed after node B syncs + WaitUtils.waitFor( + () -> + assertThat(currentHeight(permissionedNodeB)) + .isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight))); + + permissionedNodeB.verify(connectionIsAllowed(permissionedNodeA, permissionedNodeB)); + } + + private BigInteger currentHeight(final Node node) { + return node.execute(ethTransactions.blockNumber()); + } +}