remove tests and associated classes for smart contract permissioning (#8372)

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
Sally MacFarlane
2025-03-05 12:58:14 +10:00
committed by GitHub
parent c38eb8cae9
commit 6361ef5feb
34 changed files with 0 additions and 3389 deletions

View File

@@ -1,37 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.condition.perm;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.AccountSmartContractPermissioningTransactions;
public class AccountSmartContractPermissioningConditions {
private final AccountSmartContractPermissioningTransactions transactions;
public AccountSmartContractPermissioningConditions(
final AccountSmartContractPermissioningTransactions transactions) {
this.transactions = transactions;
}
public Condition accountIsAllowed(final String address, final Account account) {
return new WaitForTrueResponse(transactions.isAccountAllowed(address, account));
}
public Condition accountIsForbidden(final String address, final Account account) {
return new WaitForFalseResponse(transactions.isAccountAllowed(address, account));
}
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.condition.perm;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.NodeSmartContractPermissioningTransactions;
public class NodeSmartContractPermissioningConditions {
private final NodeSmartContractPermissioningTransactions transactions;
public NodeSmartContractPermissioningConditions(
final NodeSmartContractPermissioningTransactions transactions) {
this.transactions = transactions;
}
public Condition nodeIsAllowed(final String address, final Node node) {
return new WaitForTrueResponse(transactions.isNodeAllowed(address, node));
}
public Condition nodeIsForbidden(final String address, final Node node) {
return new WaitForFalseResponse(transactions.isNodeAllowed(address, node));
}
public Condition connectionIsAllowed(final String address, final Node source, final Node target) {
return new WaitForTrueResponse(transactions.isConnectionAllowed(address, source, target));
}
public Condition connectionIsForbidden(
final String address, final Node source, final Node target) {
return new WaitForFalseResponse(transactions.isConnectionAllowed(address, source, target));
}
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.condition.perm;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.NodeSmartContractPermissioningV2Transactions;
public class NodeSmartContractPermissioningV2Conditions {
private final NodeSmartContractPermissioningV2Transactions transactions;
public NodeSmartContractPermissioningV2Conditions(
final NodeSmartContractPermissioningV2Transactions transactions) {
this.transactions = transactions;
}
public Condition connectionIsAllowed(final String address, final Node node) {
return new WaitForTrueResponse(transactions.isConnectionAllowed(address, node));
}
public Condition connectionIsAllowed(final String address, final EnodeURL enodeURL) {
return new WaitForTrueResponse(transactions.isConnectionAllowed(address, enodeURL));
}
public Condition connectionIsForbidden(final String address, final Node node) {
return new WaitForFalseResponse(transactions.isConnectionAllowed(address, node));
}
public Condition connectionIsForbidden(final String address, final EnodeURL enodeURL) {
return new WaitForFalseResponse(transactions.isConnectionAllowed(address, enodeURL));
}
}

View File

@@ -1,78 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class AccountSmartContractPermissioningAllowAccountTransaction implements Transaction<Hash> {
private static final Bytes ADD_ACCOUNT_SIGNATURE =
org.hyperledger.besu.crypto.Hash.keccak256(Bytes.of("addAccount(address)".getBytes(UTF_8)))
.slice(0, 4);
private final Account sender;
private final Address contractAddress;
private final Address account;
public AccountSmartContractPermissioningAllowAccountTransaction(
final Account sender, final Address contractAddress, final Address account) {
this.sender = sender;
this.contractAddress = contractAddress;
this.account = account;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final Bytes payload =
Bytes.concatenate(
ADD_ACCOUNT_SIGNATURE, Bytes.fromHexString("0x000000000000000000000000"), account);
final RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1000),
BigInteger.valueOf(100_000),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
}

View File

@@ -1,79 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class AccountSmartContractPermissioningForbidAccountTransaction
implements Transaction<Hash> {
private static final Bytes REMOVE_ACCOUNT_SIGNATURE =
org.hyperledger.besu.crypto.Hash.keccak256(Bytes.of("removeAccount(address)".getBytes(UTF_8)))
.slice(0, 4);
private final Account sender;
private final Address contractAddress;
private final Address account;
public AccountSmartContractPermissioningForbidAccountTransaction(
final Account sender, final Address contractAddress, final Address account) {
this.sender = sender;
this.contractAddress = contractAddress;
this.account = account;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final Bytes payload =
Bytes.concatenate(
REMOVE_ACCOUNT_SIGNATURE, Bytes.fromHexString("0x000000000000000000000000"), account);
RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1000),
BigInteger.valueOf(100_000),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.hyperledger.besu.crypto.Hash;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.protocol.core.DefaultBlockParameterName;
public class AccountSmartContractPermissioningIsAllowedTransaction implements Transaction<Boolean> {
private static final Bytes IS_ACCOUNT_ALLOWED_SIGNATURE =
Hash.keccak256(Bytes.of("whitelistContains(address)".getBytes(UTF_8))).slice(0, 4);
private final Address contractAddress;
private final Address account;
public AccountSmartContractPermissioningIsAllowedTransaction(
final Address contractAddress, final Address account) {
this.contractAddress = contractAddress;
this.account = account;
}
@Override
public Boolean execute(final NodeRequests node) {
try {
final String value =
node.eth().ethCall(payload(), DefaultBlockParameterName.LATEST).send().getValue();
return checkTransactionResult(Bytes.fromHexString(value));
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
// Checks the returned bytes from the permissioning contract call to see if it's a value we
// understand
static Boolean checkTransactionResult(final Bytes result) {
// booleans are padded to 32 bytes
if (result.size() != 32) {
throw new IllegalArgumentException("Unexpected result size");
}
// 0 is false
if (result.equals(
Bytes.fromHexString(
"0x0000000000000000000000000000000000000000000000000000000000000000"))) {
return false;
// 1 filled to 32 bytes is true
} else if (result.equals(
Bytes.fromHexString(
"0x0000000000000000000000000000000000000000000000000000000000000001"))) {
return true;
// Anything else is wrong
} else {
throw new IllegalStateException("Unexpected result form");
}
}
private org.web3j.protocol.core.methods.request.Transaction payload() {
final Bytes payload =
Bytes.concatenate(
IS_ACCOUNT_ALLOWED_SIGNATURE,
Bytes.fromHexString("0x000000000000000000000000"),
account);
return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction(
null, null, null, null, contractAddress.toString(), payload.toString());
}
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
public class AccountSmartContractPermissioningTransactions {
private final Accounts accounts;
public AccountSmartContractPermissioningTransactions(final Accounts accounts) {
this.accounts = accounts;
}
public Transaction<Hash> allowAccount(final String contractAddress, final Account account) {
return new AccountSmartContractPermissioningAllowAccountTransaction(
accounts.getPrimaryBenefactor(),
Address.fromHexString(contractAddress),
Address.fromHexString(account.getAddress()));
}
public Transaction<Hash> forbidAccount(final String contractAddress, final Account account) {
return new AccountSmartContractPermissioningForbidAccountTransaction(
accounts.getPrimaryBenefactor(),
Address.fromHexString(contractAddress),
Address.fromHexString(account.getAddress()));
}
public Transaction<Boolean> isAccountAllowed(
final String contractAddress, final Account account) {
return new AccountSmartContractPermissioningIsAllowedTransaction(
Address.fromHexString(contractAddress), Address.fromHexString(account.getAddress()));
}
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.datatypes.Function;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class NodeSmartContractPermissioningAllowNodeByURLV2Transaction
implements Transaction<Hash> {
private final Account sender;
private final Address contractAddress;
private final EnodeURL enodeUrl;
public NodeSmartContractPermissioningAllowNodeByURLV2Transaction(
final Account sender, final Address contractAddress, final EnodeURL enodeUrl) {
this.sender = sender;
this.contractAddress = contractAddress;
this.enodeUrl = enodeUrl;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final Bytes payload = createPayload(enodeUrl);
RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1_000L),
BigInteger.valueOf(3_000_000L),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
private Bytes createPayload(final EnodeURL enodeUrl) {
try {
final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString();
final String address = enodeUrl.toURI().getHost();
final int port = enodeUrl.getListeningPortOrZero();
final Function addNodeFunction =
FunctionEncoder.makeFunction(
"addEnode",
List.of("string", "string", "uint16"),
List.of(hexNodeIdString, address, port),
Collections.emptyList());
return Bytes.fromHexString(FunctionEncoder.encode(addNodeFunction));
} catch (Exception e) {
throw new RuntimeException("Error adding node to allowlist", e);
}
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class NodeSmartContractPermissioningAllowNodeTransaction implements Transaction<Hash> {
private static final Bytes ADD_ENODE_SIGNATURE =
org.hyperledger.besu.crypto.Hash.keccak256(
Bytes.of("addEnode(bytes32,bytes32,bytes16,uint16)".getBytes(UTF_8)))
.slice(0, 4);
private final Account sender;
private final Address contractAddress;
private final Node node;
public NodeSmartContractPermissioningAllowNodeTransaction(
final Account sender, final Address contractAddress, final Node node) {
this.sender = sender;
this.contractAddress = contractAddress;
this.node = node;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final String enodeURL = ((RunnableNode) node).enodeUrl().toASCIIString();
final Bytes payload =
NodeSmartContractPermissioningController.createPayload(
ADD_ENODE_SIGNATURE, EnodeURLImpl.fromString(enodeURL));
RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1000),
BigInteger.valueOf(100_000),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.datatypes.Function;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class NodeSmartContractPermissioningAllowNodeV2Transaction implements Transaction<Hash> {
private final Account sender;
private final Address contractAddress;
private final Node node;
public NodeSmartContractPermissioningAllowNodeV2Transaction(
final Account sender, final Address contractAddress, final Node node) {
this.sender = sender;
this.contractAddress = contractAddress;
this.node = node;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final EnodeURL enodeURL = EnodeURLImpl.fromURI(((RunnableNode) node).enodeUrl());
final Bytes payload = createPayload(enodeURL);
RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1_000L),
BigInteger.valueOf(3_000_000L),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
private Bytes createPayload(final EnodeURL enodeUrl) {
try {
final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString();
final String address = enodeUrl.getIp().getHostAddress();
final int port = enodeUrl.getListeningPortOrZero();
final Function addNodeFunction =
FunctionEncoder.makeFunction(
"addEnode",
List.of("string", "string", "uint16"),
List.of(hexNodeIdString, address, port),
Collections.emptyList());
return Bytes.fromHexString(FunctionEncoder.encode(addNodeFunction));
} catch (Exception e) {
throw new RuntimeException("Error adding node to allowlist", e);
}
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractV2PermissioningController;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.datatypes.Function;
import org.web3j.protocol.core.DefaultBlockParameterName;
public class NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction
implements Transaction<Boolean> {
private final Address contractAddress;
private final EnodeURL enodeUrl;
public NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction(
final Address contractAddress, final EnodeURL enodeUrl) {
this.contractAddress = contractAddress;
this.enodeUrl = enodeUrl;
}
@Override
public Boolean execute(final NodeRequests node) {
try {
final String value =
node.eth().ethCall(payload(), DefaultBlockParameterName.LATEST).send().getValue();
return Bytes.fromHexString(value)
.equals(NodeSmartContractV2PermissioningController.TRUE_RESPONSE);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private org.web3j.protocol.core.methods.request.Transaction payload() {
final Bytes payload = createPayload(this.enodeUrl);
return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction(
null, null, null, null, contractAddress.toString(), payload.toString());
}
private Bytes createPayload(final EnodeURL enodeUrl) {
try {
final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString();
final String address = enodeUrl.toURI().getHost();
final int port = enodeUrl.getListeningPortOrZero();
final Function connectionAllowedFunction =
FunctionEncoder.makeFunction(
"connectionAllowed",
List.of("string", "string", "uint16"),
List.of(hexNodeIdString, address, port),
Collections.emptyList());
return Bytes.fromHexString(FunctionEncoder.encode(connectionAllowedFunction));
} catch (Exception e) {
throw new RuntimeException("Error calling connectionAllowed", e);
}
}
}

View File

@@ -1,78 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController.checkTransactionResult;
import org.hyperledger.besu.crypto.Hash;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.protocol.core.DefaultBlockParameterName;
public class NodeSmartContractPermissioningConnectionIsAllowedTransaction
implements Transaction<Boolean> {
private static final Bytes IS_CONNECTION_ALLOWED_SIGNATURE =
Hash.keccak256(
Bytes.of(
"connectionAllowed(bytes32,bytes32,bytes16,uint16,bytes32,bytes32,bytes16,uint16)"
.getBytes(UTF_8)))
.slice(0, 4);
private final Address contractAddress;
private final Node source;
private final Node target;
public NodeSmartContractPermissioningConnectionIsAllowedTransaction(
final Address contractAddress, final Node source, final Node target) {
this.contractAddress = contractAddress;
this.source = source;
this.target = target;
}
@Override
public Boolean execute(final NodeRequests node) {
try {
final String value =
node.eth().ethCall(payload(), DefaultBlockParameterName.LATEST).send().getValue();
return checkTransactionResult(Bytes.fromHexString(value));
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private org.web3j.protocol.core.methods.request.Transaction payload() {
final String sourceEnodeURL = ((RunnableNode) source).enodeUrl().toASCIIString();
final String targetEnodeURL = ((RunnableNode) target).enodeUrl().toASCIIString();
final Bytes payload =
NodeSmartContractPermissioningController.createPayload(
IS_CONNECTION_ALLOWED_SIGNATURE,
EnodeURLImpl.fromString(sourceEnodeURL),
EnodeURLImpl.fromString(targetEnodeURL));
return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction(
null, null, null, null, contractAddress.toString(), payload.toString());
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractV2PermissioningController;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.datatypes.Function;
import org.web3j.protocol.core.DefaultBlockParameterName;
public class NodeSmartContractPermissioningConnectionIsAllowedV2Transaction
implements Transaction<Boolean> {
private final Address contractAddress;
private final Node node;
public NodeSmartContractPermissioningConnectionIsAllowedV2Transaction(
final Address contractAddress, final Node node) {
this.contractAddress = contractAddress;
this.node = node;
}
@Override
public Boolean execute(final NodeRequests node) {
try {
final String value =
node.eth().ethCall(payload(), DefaultBlockParameterName.LATEST).send().getValue();
return Bytes.fromHexString(value)
.equals(NodeSmartContractV2PermissioningController.TRUE_RESPONSE);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private org.web3j.protocol.core.methods.request.Transaction payload() {
final EnodeURL enodeURL = EnodeURLImpl.fromURI(((RunnableNode) node).enodeUrl());
final Bytes payload = createPayload(enodeURL);
return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction(
null, null, null, null, contractAddress.toString(), payload.toString());
}
private Bytes createPayload(final EnodeURL enodeUrl) {
try {
final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString();
final String address = enodeUrl.getIp().getHostAddress();
final int port = enodeUrl.getListeningPortOrZero();
final Function connectionAllowedFunction =
FunctionEncoder.makeFunction(
"connectionAllowed",
List.of("string", "string", "uint16"),
List.of(hexNodeIdString, address, port),
Collections.emptyList());
return Bytes.fromHexString(FunctionEncoder.encode(connectionAllowedFunction));
} catch (Exception e) {
throw new RuntimeException("Error calling connectionAllowed", e);
}
}
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.datatypes.Function;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class NodeSmartContractPermissioningForbidNodeByURLV2Transaction
implements Transaction<Hash> {
private final Account sender;
private final Address contractAddress;
private final EnodeURL enodeUrl;
public NodeSmartContractPermissioningForbidNodeByURLV2Transaction(
final Account sender, final Address contractAddress, final EnodeURL enodeUrl) {
this.sender = sender;
this.contractAddress = contractAddress;
this.enodeUrl = enodeUrl;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final Bytes payload = createPayload(this.enodeUrl);
RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1000),
BigInteger.valueOf(3_000_000L),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
private Bytes createPayload(final EnodeURL enodeUrl) {
try {
final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString();
final String address = enodeUrl.toURI().getHost();
final int port = enodeUrl.getListeningPortOrZero();
final Function removeNodeFunction =
FunctionEncoder.makeFunction(
"removeEnode",
List.of("string", "string", "uint16"),
List.of(hexNodeIdString, address, port),
Collections.emptyList());
return Bytes.fromHexString(FunctionEncoder.encode(removeNodeFunction));
} catch (Exception e) {
throw new RuntimeException("Error removing node from allowlist", e);
}
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class NodeSmartContractPermissioningForbidNodeTransaction implements Transaction<Hash> {
private static final Bytes REMOVE_ENODE_SIGNATURE =
org.hyperledger.besu.crypto.Hash.keccak256(
Bytes.of("removeEnode(bytes32,bytes32,bytes16,uint16)".getBytes(UTF_8)))
.slice(0, 4);
private final Account sender;
private final Address contractAddress;
private final Node node;
public NodeSmartContractPermissioningForbidNodeTransaction(
final Account sender, final Address contractAddress, final Node node) {
this.sender = sender;
this.contractAddress = contractAddress;
this.node = node;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final String enodeURL = ((RunnableNode) node).enodeUrl().toASCIIString();
final Bytes payload =
NodeSmartContractPermissioningController.createPayload(
REMOVE_ENODE_SIGNATURE, EnodeURLImpl.fromString(enodeURL));
RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1000),
BigInteger.valueOf(100_000),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static org.web3j.utils.Numeric.toHexString;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.datatypes.Function;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
public class NodeSmartContractPermissioningForbidNodeV2Transaction implements Transaction<Hash> {
private final Account sender;
private final Address contractAddress;
private final Node node;
public NodeSmartContractPermissioningForbidNodeV2Transaction(
final Account sender, final Address contractAddress, final Node node) {
this.sender = sender;
this.contractAddress = contractAddress;
this.node = node;
}
@Override
public Hash execute(final NodeRequests node) {
final String signedTransactionData = signedTransactionData();
try {
String hash =
node.eth().ethSendRawTransaction(signedTransactionData).send().getTransactionHash();
return Hash.fromHexString(hash);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private String signedTransactionData() {
final EnodeURL enodeURL = EnodeURLImpl.fromURI(((RunnableNode) node).enodeUrl());
final Bytes payload = createPayload(enodeURL);
RawTransaction transaction =
RawTransaction.createTransaction(
sender.getNextNonce(),
BigInteger.valueOf(1000),
BigInteger.valueOf(3_000_000L),
contractAddress.toString(),
payload.toString());
return toHexString(
TransactionEncoder.signMessage(transaction, sender.web3jCredentialsOrThrow()));
}
private Bytes createPayload(final EnodeURL enodeUrl) {
try {
final String hexNodeIdString = enodeUrl.getNodeId().toUnprefixedHexString();
final String address = enodeUrl.getIp().getHostAddress();
final int port = enodeUrl.getListeningPortOrZero();
final Function removeNodeFunction =
FunctionEncoder.makeFunction(
"removeEnode",
List.of("string", "string", "uint16"),
List.of(hexNodeIdString, address, port),
Collections.emptyList());
return Bytes.fromHexString(FunctionEncoder.encode(removeNodeFunction));
} catch (Exception e) {
throw new RuntimeException("Error removing node from allowlist", e);
}
}
}

View File

@@ -1,92 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.hyperledger.besu.crypto.Hash;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.permissioning.NodeSmartContractPermissioningController;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.protocol.core.DefaultBlockParameterName;
public class NodeSmartContractPermissioningIsAllowedTransaction implements Transaction<Boolean> {
private static final Bytes IS_NODE_ALLOWED_SIGNATURE =
Hash.keccak256(Bytes.of("enodeAllowed(bytes32,bytes32,bytes16,uint16)".getBytes(UTF_8)))
.slice(0, 4);
private final Address contractAddress;
private final Node node;
public NodeSmartContractPermissioningIsAllowedTransaction(
final Address contractAddress, final Node node) {
this.contractAddress = contractAddress;
this.node = node;
}
@Override
public Boolean execute(final NodeRequests node) {
try {
final String value =
node.eth().ethCall(payload(), DefaultBlockParameterName.LATEST).send().getValue();
return checkTransactionResult(Bytes.fromHexString(value));
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
// Checks the returned bytes from the permissioning contract call to see if it's a value we
// understand
static Boolean checkTransactionResult(final Bytes result) {
// booleans are padded to 32 bytes
if (result.size() != 32) {
throw new IllegalArgumentException("Unexpected result size");
}
// 0 is false
if (result.equals(
Bytes.fromHexString(
"0x0000000000000000000000000000000000000000000000000000000000000000"))) {
return false;
// 1 filled to 32 bytes is true
} else if (result.equals(
Bytes.fromHexString(
"0x0000000000000000000000000000000000000000000000000000000000000001"))) {
return true;
// Anything else is wrong
} else {
throw new IllegalStateException("Unexpected result form");
}
}
private org.web3j.protocol.core.methods.request.Transaction payload() {
final String sourceEnodeURL = ((RunnableNode) node).enodeUrl().toASCIIString();
final Bytes payload =
NodeSmartContractPermissioningController.createPayload(
IS_NODE_ALLOWED_SIGNATURE, EnodeURLImpl.fromString(sourceEnodeURL));
return org.web3j.protocol.core.methods.request.Transaction.createFunctionCallTransaction(
null, null, null, null, contractAddress.toString(), payload.toString());
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
public class NodeSmartContractPermissioningTransactions {
private final Accounts accounts;
public NodeSmartContractPermissioningTransactions(final Accounts accounts) {
this.accounts = accounts;
}
public Transaction<Hash> allowNode(final String contractAddress, final Node node) {
return new NodeSmartContractPermissioningAllowNodeTransaction(
accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), node);
}
public Transaction<Hash> forbidNode(final String contractAddress, final Node node) {
return new NodeSmartContractPermissioningForbidNodeTransaction(
accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), node);
}
public Transaction<Boolean> isNodeAllowed(final String contractAddress, final Node node) {
return new NodeSmartContractPermissioningIsAllowedTransaction(
Address.fromHexString(contractAddress), node);
}
public Transaction<Boolean> isConnectionAllowed(
final String contractAddress, final Node source, final Node target) {
return new NodeSmartContractPermissioningConnectionIsAllowedTransaction(
Address.fromHexString(contractAddress), source, target);
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.perm;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
public class NodeSmartContractPermissioningV2Transactions {
private final Accounts accounts;
public NodeSmartContractPermissioningV2Transactions(final Accounts accounts) {
this.accounts = accounts;
}
public Transaction<Hash> allowNode(final String contractAddress, final Node node) {
return new NodeSmartContractPermissioningAllowNodeV2Transaction(
accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), node);
}
public Transaction<Hash> allowNode(final String contractAddress, final EnodeURL enodeURL) {
return new NodeSmartContractPermissioningAllowNodeByURLV2Transaction(
accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), enodeURL);
}
public Transaction<Hash> forbidNode(final String contractAddress, final Node node) {
return new NodeSmartContractPermissioningForbidNodeV2Transaction(
accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), node);
}
public Transaction<Hash> forbidNode(final String contractAddress, final EnodeURL enodeURL) {
return new NodeSmartContractPermissioningForbidNodeByURLV2Transaction(
accounts.getPrimaryBenefactor(), Address.fromHexString(contractAddress), enodeURL);
}
public Transaction<Boolean> isConnectionAllowed(final String contractAddress, final Node node) {
return new NodeSmartContractPermissioningConnectionIsAllowedV2Transaction(
Address.fromHexString(contractAddress), node);
}
public Transaction<Boolean> isConnectionAllowed(
final String contractAddress, final EnodeURL enodeURL) {
return new NodeSmartContractPermissioningConnectionIsAllowedByURLV2Transaction(
Address.fromHexString(contractAddress), enodeURL);
}
}

View File

@@ -1,123 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction;
import java.math.BigInteger;
import java.util.Arrays;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@Disabled("permissioning tests flaky with timeouts")
public class AccountLocalAndOnchainPermissioningAcceptanceTest
extends AccountSmartContractPermissioningAcceptanceTestBase {
private Account senderC;
@BeforeEach
public void setUp() {
senderC = accounts.createAccount("Account-C");
}
@Test
public void testAccountCannotSendTxWhenNotOnLocalAllowList() {
// Onchain allowlist: Primary, Secondary, C
// Local allowlist: Primary, Secondary
final Node node =
permissionedNode(
"node1",
Arrays.asList(
accounts.getPrimaryBenefactor().getAddress(),
accounts.getSecondaryBenefactor().getAddress()));
permissionedCluster.start(node);
// ensure SenderC has got some ether available
node.execute(accountTransactions.createTransfer(senderC, 10));
node.verify(senderC.balanceEquals(10));
// add accounts to onchain allowlist
node.execute(allowAccount(accounts.getPrimaryBenefactor()));
node.verify(accountIsAllowed(accounts.getPrimaryBenefactor()));
node.execute(allowAccount(accounts.getSecondaryBenefactor()));
node.verify(accountIsAllowed(accounts.getSecondaryBenefactor()));
node.execute(allowAccount(senderC));
node.verify(accountIsAllowed(senderC));
// sender C should not be able to send Tx
verifyTransferForbidden(node, senderC, accounts.getSecondaryBenefactor());
}
@Test
public void testAccountCannotSendTxWhenNotOnOnchainAllowList() {
// Onchain allowlist: Primary, Secondary, Receiver
// Local allowlist: Primary, Secondary, C, Receiver
final Account receiverAccount = accounts.createAccount("Rec-A");
final Node node =
permissionedNode(
"node1",
Arrays.asList(
accounts.getPrimaryBenefactor().getAddress(),
accounts.getSecondaryBenefactor().getAddress(),
senderC.getAddress(),
receiverAccount.getAddress()));
permissionedCluster.start(node);
// ensure SenderC has got some ether available
node.execute(accountTransactions.createTransfer(senderC, 10));
node.verify(senderC.balanceEquals(10));
// add accounts to onchain allowlist
node.execute(allowAccount(accounts.getPrimaryBenefactor()));
node.verify(accountIsAllowed(accounts.getPrimaryBenefactor()));
node.execute(allowAccount(accounts.getSecondaryBenefactor()));
node.verify(accountIsAllowed(accounts.getSecondaryBenefactor()));
node.execute(allowAccount(receiverAccount));
node.verify(accountIsAllowed(receiverAccount));
// verify senderC is forbidden because it is not on Onchain allowlist
node.verify(accountIsForbidden(senderC));
// sender C should not be able to send Tx
verifyTransferForbidden(node, senderC, accounts.getSecondaryBenefactor());
// final check, other account should be able to send tx
node.execute(
accountTransactions.createTransfer(accounts.getPrimaryBenefactor(), receiverAccount, 5));
node.verify(receiverAccount.balanceEquals(5));
}
private void verifyTransferForbidden(
final Node node, final Account sender, final Account beneficiary) {
final BigInteger nonce = node.execute(ethTransactions.getTransactionCount(sender.getAddress()));
final TransferTransaction transfer =
accountTransactions.createTransfer(sender, beneficiary, 1, nonce);
node.verify(
eth.expectEthSendRawTransactionException(
transfer.signedTransactionData(),
"Sender account not authorized to send transactions"));
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTransaction;
import java.math.BigInteger;
import java.util.Collections;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class AccountSmartContractPermissioningAcceptanceTest
extends AccountSmartContractPermissioningAcceptanceTestBase {
private Node node;
private Account allowedSender;
private Account otherAccount;
@BeforeEach
public void setUp() {
node = permissionedNode("node1", Collections.emptyList());
permissionedCluster.start(node);
allowedSender = accounts.createAccount("authorized-account");
otherAccount = accounts.createAccount("other-account");
// ensure primary benefactor is permitted (account used to permit/forbid other accounts)
node.execute(allowAccount(accounts.getPrimaryBenefactor()));
node.verify(accountIsAllowed(accounts.getPrimaryBenefactor()));
// ensure allowedSender has got some ether available
node.execute(accountTransactions.createTransfer(allowedSender, 10));
node.verify(allowedSender.balanceEquals(10));
}
@Test
public void allowedAccountCanTransferValue() {
node.execute(allowAccount(allowedSender));
node.verify(accountIsAllowed(allowedSender));
node.execute(accountTransactions.createTransfer(allowedSender, otherAccount, 5));
node.verify(otherAccount.balanceEquals(5));
}
@Test
public void forbiddenAccountCannotTransferValue() {
node.execute(forbidAccount(allowedSender));
node.verify(accountIsForbidden(allowedSender));
verifyTransferForbidden(allowedSender, otherAccount);
}
private void verifyTransferForbidden(final Account sender, final Account beneficiary) {
final BigInteger nonce = node.execute(ethTransactions.getTransactionCount(sender.getAddress()));
final TransferTransaction transfer =
accountTransactions.createTransfer(sender, beneficiary, 1, nonce);
node.verify(
eth.expectEthSendRawTransactionException(
transfer.signedTransactionData(),
"Sender account not authorized to send transactions"));
}
}

View File

@@ -1,105 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.condition.perm.AccountSmartContractPermissioningConditions;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.permissioning.PermissionedNodeBuilder;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.AccountSmartContractPermissioningTransactions;
import java.io.IOException;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
class AccountSmartContractPermissioningAcceptanceTestBase extends AcceptanceTestBase {
private final AccountSmartContractPermissioningTransactions smartContractAccountPermissioning;
private final AccountSmartContractPermissioningConditions
accountSmartContractPermissioningConditions;
private static final String CONTRACT_ADDRESS = "0x0000000000000000000000000000000000008888";
private static final String GENESIS_FILE = "/permissioning/simple_permissioning_genesis.json";
protected final Cluster permissionedCluster;
protected AccountSmartContractPermissioningAcceptanceTestBase() {
super();
smartContractAccountPermissioning = new AccountSmartContractPermissioningTransactions(accounts);
accountSmartContractPermissioningConditions =
new AccountSmartContractPermissioningConditions(smartContractAccountPermissioning);
this.permissionedCluster = permissionedCluster();
}
private Cluster permissionedCluster() {
final ClusterConfiguration clusterConfiguration =
new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build();
return new Cluster(clusterConfiguration, net);
}
protected Node permissionedNode(final String name, final List<String> accountsPermittedInConfig) {
PermissionedNodeBuilder permissionedNodeBuilder =
this.permissionedNodeBuilder
.name(name)
.genesisFile(GENESIS_FILE)
.accountsContractEnabled(CONTRACT_ADDRESS);
if (accountsPermittedInConfig != null && !accountsPermittedInConfig.isEmpty()) {
permissionedNodeBuilder.accountsPermittedInConfig(accountsPermittedInConfig);
}
return permissionedNodeBuilder.build();
}
protected Node node(final String name) {
try {
return besu.createCustomGenesisNode(name, GENESIS_FILE, false);
} catch (IOException e) {
throw new RuntimeException("Error creating node", e);
}
}
@AfterEach
@Override
public void tearDownAcceptanceTestBase() {
permissionedCluster.stop();
super.tearDownAcceptanceTestBase();
}
protected Transaction<Hash> allowAccount(final Account account) {
return smartContractAccountPermissioning.allowAccount(CONTRACT_ADDRESS, account);
}
protected Transaction<Hash> forbidAccount(final Account account) {
return smartContractAccountPermissioning.forbidAccount(CONTRACT_ADDRESS, account);
}
protected Condition accountIsAllowed(final Account account) {
return accountSmartContractPermissioningConditions.accountIsAllowed(CONTRACT_ADDRESS, account);
}
protected Condition accountIsForbidden(final Account account) {
return accountSmartContractPermissioningConditions.accountIsForbidden(
CONTRACT_ADDRESS, account);
}
}

View File

@@ -1,117 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@Disabled("permissioning tests flaky with timeouts")
public class NodeLocalAndOnchainPermissioningAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
private Node bootnode;
private Node permissionedNode;
private Node allowedNode;
private Node forbiddenNode;
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");
allowedNode = node("allowed-node");
permissionedCluster.start(bootnode, allowedNode, forbiddenNode);
}
@Test
public void testNodeCannotConnectWhenAllowedOnchainButNotLocally() {
// add permissioned node after cluster start because we need enode URI for local config
permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode);
permissionedCluster.addNode(permissionedNode);
// update Onchain smart contract with allowed nodes
permissionedNode.execute(allowNode(bootnode));
permissionedNode.verify(nodeIsAllowed(bootnode));
permissionedNode.execute(allowNode(allowedNode));
permissionedNode.verify(nodeIsAllowed(allowedNode));
permissionedNode.execute(allowNode(permissionedNode));
permissionedNode.verify(nodeIsAllowed(permissionedNode));
permissionedNode.execute(allowNode(forbiddenNode));
permissionedNode.verify(nodeIsAllowed(forbiddenNode));
permissionedNodeShouldDiscoverOnlyAllowedNodes();
}
@Test
public void testNodeCannotConnectWhenAllowedLocallyButNotOnchain() {
// onchain allowlist: A, B
// local allowlist: A, B, C
// add permissioned node after cluster start because we need enode URI for local config
permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode, forbiddenNode);
permissionedCluster.addNode(permissionedNode);
// update Onchain smart contract with allowed nodes
permissionedNode.execute(allowNode(bootnode));
permissionedNode.verify(nodeIsAllowed(bootnode));
permissionedNode.execute(allowNode(allowedNode));
permissionedNode.verify(nodeIsAllowed(allowedNode));
permissionedNode.execute(allowNode(permissionedNode));
permissionedNode.verify(nodeIsAllowed(permissionedNode));
permissionedNodeShouldDiscoverOnlyAllowedNodes();
}
@Test
public void testNodesCanConnectWhenAllowedBothOnchainAndLocally() {
// add permissioned node after cluster start because we need enode URI for local config
permissionedNode = permissionedNode("permissioned-node", bootnode, allowedNode, forbiddenNode);
permissionedCluster.addNode(permissionedNode);
// update Onchain smart contract with allowed nodes
permissionedNode.execute(allowNode(bootnode));
permissionedNode.verify(nodeIsAllowed(bootnode));
permissionedNode.execute(allowNode(allowedNode));
permissionedNode.verify(nodeIsAllowed(allowedNode));
permissionedNode.execute(allowNode(permissionedNode));
permissionedNode.verify(nodeIsAllowed(permissionedNode));
permissionedNode.execute(allowNode(forbiddenNode));
permissionedNode.verify(nodeIsAllowed(forbiddenNode));
bootnode.verify(net.awaitPeerCount(3));
allowedNode.verify(net.awaitPeerCount(3));
forbiddenNode.verify(net.awaitPeerCount(3));
permissionedNode.verify(net.awaitPeerCount(3));
}
private void permissionedNodeShouldDiscoverOnlyAllowedNodes() {
bootnode.verify(net.awaitPeerCount(3));
allowedNode.verify(net.awaitPeerCount(3));
forbiddenNode.verify(net.awaitPeerCount(2));
permissionedNode.verify(net.awaitPeerCount(2));
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
private Node bootnode;
private Node permissionedNode;
private Node allowedNode;
private Node forbiddenNode;
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");
allowedNode = node("allowed-node");
permissionedNode = permissionedNode("permissioned-node");
permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode);
// updating permissioning smart contract with allowed nodes
permissionedNode.verify(nodeIsForbidden(bootnode));
permissionedNode.execute(allowNode(bootnode));
permissionedNode.verify(nodeIsAllowed(bootnode));
permissionedNode.verify(admin.hasPeer(bootnode));
permissionedNode.execute(allowNode(allowedNode));
permissionedNode.verify(nodeIsAllowed(allowedNode));
permissionedNode.execute(allowNode(permissionedNode));
permissionedNode.verify(nodeIsAllowed(permissionedNode));
permissionedNode.verify(admin.addPeer(allowedNode));
allowedNode.verify(eth.syncingStatus(false));
bootnode.verify(eth.syncingStatus(false));
permissionedNode.verify(eth.syncingStatus(false));
forbiddenNode.verify(eth.syncingStatus(false));
}
@Test
@Disabled("test is flaky")
public void permissionedNodeShouldPeerOnlyWithAllowedNodes() {
bootnode.verify(net.awaitPeerCount(3));
allowedNode.verify(net.awaitPeerCount(3));
forbiddenNode.verify(net.awaitPeerCount(2));
permissionedNode.verify(net.awaitPeerCount(2));
}
@Test
public void permissionedNodeShouldDisconnectFromNodeNotPermittedAnymore() {
permissionedNode.execute(forbidNode(allowedNode));
permissionedNode.verify(connectionIsForbidden(permissionedNode, allowedNode));
permissionedNode.verify(net.awaitPeerCount(1));
}
@Test
public void permissioningUpdatesPropagateThroughNetwork() {
// connection to newly permitted node is allowed
allowedNode.execute(allowNode(forbiddenNode));
allowedNode.verify(connectionIsAllowed(permissionedNode, forbiddenNode));
// permissioning changes in peer should propagate to permissioned node
permissionedNode.verify(connectionIsAllowed(permissionedNode, forbiddenNode));
permissionedNode.verify(admin.addPeer(forbiddenNode));
permissionedNode.verify(net.awaitPeerCount(3));
}
@Test
public void onchainPermissioningAllowlistShouldPersistAcrossRestarts() {
permissionedCluster.stop();
permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode);
permissionedNode.verify(nodeIsAllowed(allowedNode));
permissionedNode.verify(nodeIsAllowed(bootnode));
permissionedNode.verify(nodeIsAllowed(permissionedNode));
}
}

View File

@@ -1,134 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.condition.perm.NodeSmartContractPermissioningConditions;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.permissioning.PermissionedNodeBuilder;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.NodeSmartContractPermissioningTransactions;
import java.io.IOException;
import org.junit.jupiter.api.AfterEach;
class NodeSmartContractPermissioningAcceptanceTestBase extends AcceptanceTestBase {
private final NodeSmartContractPermissioningTransactions smartContractNodePermissioning;
private final NodeSmartContractPermissioningConditions nodeSmartContractPermissioningConditions;
protected static final String CONTRACT_ADDRESS = "0x0000000000000000000000000000000000009999";
protected static final String GENESIS_FILE = "/permissioning/simple_permissioning_genesis.json";
protected final Cluster permissionedCluster;
protected NodeSmartContractPermissioningAcceptanceTestBase() {
super();
smartContractNodePermissioning = new NodeSmartContractPermissioningTransactions(accounts);
nodeSmartContractPermissioningConditions =
new NodeSmartContractPermissioningConditions(smartContractNodePermissioning);
this.permissionedCluster = permissionedCluster();
}
private Cluster permissionedCluster() {
final ClusterConfiguration clusterConfiguration =
new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build();
return new Cluster(clusterConfiguration, net);
}
protected Node permissionedNode(final String name, final Node... localConfigAllowedNodes) {
return permissionedNode(name, GENESIS_FILE, localConfigAllowedNodes);
}
protected Node permissionedNode(
final String name, final String genesisFile, final Node... localConfigAllowedNodes) {
PermissionedNodeBuilder permissionedNodeBuilder =
this.permissionedNodeBuilder
.name(name)
.genesisFile(genesisFile)
.nodesContractEnabled(CONTRACT_ADDRESS);
if (localConfigAllowedNodes != null && localConfigAllowedNodes.length > 0) {
permissionedNodeBuilder.nodesPermittedInConfig(localConfigAllowedNodes);
}
return permissionedNodeBuilder.build();
}
protected Node bootnode(final String name) {
return bootnode(name, GENESIS_FILE);
}
protected Node bootnode(final String name, final String genesisFile) {
try {
return besu.createCustomGenesisNode(name, genesisFile, true);
} catch (IOException e) {
throw new RuntimeException("Error creating node", e);
}
}
protected Node node(final String name) {
try {
return besu.createCustomGenesisNode(name, GENESIS_FILE, false);
} catch (IOException e) {
throw new RuntimeException("Error creating node", e);
}
}
protected Node miner(final String name) {
try {
return besu.createCustomGenesisNode(name, GENESIS_FILE, false, true);
} catch (IOException e) {
throw new RuntimeException("Error creating node", e);
}
}
@AfterEach
@Override
public void tearDownAcceptanceTestBase() {
permissionedCluster.stop();
super.tearDownAcceptanceTestBase();
}
protected Transaction<Hash> allowNode(final Node node) {
return smartContractNodePermissioning.allowNode(CONTRACT_ADDRESS, node);
}
protected Condition nodeIsAllowed(final Node node) {
return nodeSmartContractPermissioningConditions.nodeIsAllowed(CONTRACT_ADDRESS, node);
}
protected Transaction<Hash> forbidNode(final Node node) {
return smartContractNodePermissioning.forbidNode(CONTRACT_ADDRESS, node);
}
protected Condition nodeIsForbidden(final Node node) {
return nodeSmartContractPermissioningConditions.nodeIsForbidden(CONTRACT_ADDRESS, node);
}
protected Condition connectionIsAllowed(final Node source, final Node target) {
return nodeSmartContractPermissioningConditions.connectionIsAllowed(
CONTRACT_ADDRESS, source, target);
}
protected Condition connectionIsForbidden(final Node source, final Node target) {
return nodeSmartContractPermissioningConditions.connectionIsForbidden(
CONTRACT_ADDRESS, source, target);
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import java.io.IOException;
import java.util.Optional;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningIbft2StallAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
private static final String GENESIS_FILE =
"/permissioning/simple_permissioning_ibft_genesis.json";
@Test
public void restartedIbftClusterShouldNotStall() throws IOException {
final BesuNode bootnode = besu.createIbft2NonValidatorBootnode("bootnode", GENESIS_FILE);
final BesuNode nodeA = besu.createIbft2Node("nodeA", GENESIS_FILE);
final BesuNode nodeB = besu.createIbft2Node("nodeB", GENESIS_FILE);
permissionedCluster.start(bootnode, nodeA, nodeB);
// make sure we are producing blocks before sending any transactions
waitForBlockHeight(bootnode, 1);
// allow nodes in onchain smart contract
nodeA.execute(allowNode(bootnode));
nodeA.execute(allowNode(nodeA));
nodeA.execute(allowNode(nodeB));
// verify the nodes are allowed
nodeA.verify(nodeIsAllowed(bootnode));
nodeA.verify(nodeIsAllowed(nodeA));
nodeA.verify(nodeIsAllowed(nodeB));
permissionedCluster.stop();
// Create permissioning config
final SmartContractPermissioningConfiguration smartContractPermissioningConfiguration =
new SmartContractPermissioningConfiguration();
smartContractPermissioningConfiguration.setSmartContractNodeAllowlistEnabled(true);
smartContractPermissioningConfiguration.setNodeSmartContractAddress(
Address.fromHexString(CONTRACT_ADDRESS));
final PermissioningConfiguration permissioningConfiguration =
new PermissioningConfiguration(
Optional.empty(), Optional.of(smartContractPermissioningConfiguration));
// Set permissioning configurations on nodes
bootnode.setPermissioningConfiguration(permissioningConfiguration);
nodeA.setPermissioningConfiguration(permissioningConfiguration);
nodeB.setPermissioningConfiguration(permissioningConfiguration);
permissionedCluster.start(bootnode, nodeA, nodeB);
// Verify blockchain is progressing
permissionedCluster.verify(blockchain.reachesHeight(bootnode, 1, 120));
}
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningOutOfSyncAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
private Node bootnode;
private Node permissionedNodeA;
private Node permissionedNodeB;
@BeforeEach
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 allowlist nodes
permissionedNodeA.execute(allowNode(bootnode));
permissionedNodeA.verify(nodeIsAllowed(bootnode));
permissionedNodeA.execute(allowNode(permissionedNodeA));
permissionedNodeA.verify(nodeIsAllowed(permissionedNodeA));
permissionedNodeA.verify(admin.addPeer(bootnode));
}
@Test
@Disabled("test is flaky #7108")
public void addNodeToClusterAndVerifyNonBootNodePeerConnectionWorksAfterSync() {
final long blockchainHeight = 25L;
waitForBlockHeight(permissionedNodeA, blockchainHeight);
// verify Node A is in sync with bootnode
final var minerChainHead = bootnode.execute(ethTransactions.block());
permissionedNodeA.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
// check that connection is forbidden (before node b is permitted)
permissionedCluster.addNode(permissionedNodeB);
permissionedNodeB.verify(connectionIsForbidden(permissionedNodeA, permissionedNodeB));
// Permit Node B
permissionedNodeA.execute(allowNode(permissionedNodeB));
permissionedNodeA.verify(admin.addPeer(permissionedNodeB));
// connection should be allowed after node B syncs
waitForBlockHeight(permissionedNodeB, blockchainHeight);
permissionedNodeB.verify(connectionIsAllowed(permissionedNodeA, permissionedNodeB));
}
}

View File

@@ -1,128 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningV2AcceptanceTest
extends NodeSmartContractPermissioningV2AcceptanceTestBase {
private Node bootnode;
private Node permissionedNode;
private Node allowedNode;
private Node forbiddenNode;
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");
allowedNode = node("allowed-node");
permissionedNode = permissionedNode("permissioned-node");
permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode);
verifyAllNodesAreInSyncWithMiner();
// updating permissioning smart contract with allowed nodes
permissionedNode.execute(allowNode(bootnode));
permissionedNode.verify(connectionIsAllowed(bootnode));
permissionedNode.execute(allowNode(allowedNode));
permissionedNode.verify(connectionIsAllowed(allowedNode));
permissionedNode.execute(allowNode(permissionedNode));
permissionedNode.verify(connectionIsAllowed(permissionedNode));
}
@Test
@Disabled("test is flaky")
public void permissionedNodeShouldPeerOnlyWithAllowedNodes() {
bootnode.verify(net.awaitPeerCount(3));
allowedNode.verify(net.awaitPeerCount(3));
forbiddenNode.verify(net.awaitPeerCount(2));
permissionedNode.verify(net.awaitPeerCount(2));
}
@Test
public void permissionedNodeShouldDisconnectFromNodeNotPermittedAnymore() {
permissionedNode.verify(admin.hasPeer(bootnode));
permissionedNode.verify(admin.addPeer(allowedNode));
permissionedNode.verify(net.awaitPeerCount(2));
permissionedNode.execute(forbidNode(allowedNode));
permissionedNode.verify(connectionIsForbidden(allowedNode));
permissionedNode.verify(net.awaitPeerCount(1));
}
@Test
public void permissionedNodeShouldConnectToNewlyPermittedNode() {
permissionedNode.verify(admin.hasPeer(bootnode));
permissionedNode.verify(admin.addPeer(allowedNode));
permissionedNode.verify(net.awaitPeerCount(2));
verifyAllNodesAreInSyncWithMiner();
permissionedNode.execute(allowNode(forbiddenNode));
permissionedNode.verify(connectionIsAllowed(forbiddenNode));
permissionedNode.verify(admin.addPeer(forbiddenNode));
permissionedNode.verify(net.awaitPeerCount(3));
}
@Test
public void permissioningUpdatesPropagateThroughNetwork() {
permissionedNode.verify(admin.hasPeer(bootnode));
permissionedNode.verify(admin.addPeer(allowedNode));
permissionedNode.verify(net.awaitPeerCount(2));
verifyAllNodesAreInSyncWithMiner();
// permissioning changes in peer should propagate to permissioned node
allowedNode.execute(allowNode(forbiddenNode));
allowedNode.verify(connectionIsAllowed(forbiddenNode));
permissionedNode.verify(connectionIsAllowed(forbiddenNode));
permissionedNode.verify(admin.addPeer(forbiddenNode));
permissionedNode.verify(net.awaitPeerCount(3));
}
private void verifyAllNodesAreInSyncWithMiner() {
// verify the miner (permissionedNode) started producing blocks and other nodes are syncing
// from it
waitForBlockHeight(permissionedNode, 1);
final var minerChainHead = permissionedNode.execute(ethTransactions.block());
bootnode.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
allowedNode.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
}
@Test
public void onchainPermissioningAllowlistShouldPersistAcrossRestarts() {
permissionedCluster.stop();
permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode);
verifyAllNodesAreInSyncWithMiner();
permissionedNode.verify(connectionIsAllowed(allowedNode));
permissionedNode.verify(connectionIsAllowed(bootnode));
permissionedNode.verify(connectionIsAllowed(permissionedNode));
permissionedNode.verify(connectionIsForbidden(forbiddenNode));
}
}

View File

@@ -1,138 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.condition.perm.NodeSmartContractPermissioningV2Conditions;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.permissioning.PermissionedNodeBuilder;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.NodeSmartContractPermissioningV2Transactions;
import java.io.IOException;
import org.junit.jupiter.api.AfterEach;
class NodeSmartContractPermissioningV2AcceptanceTestBase extends AcceptanceTestBase {
private final NodeSmartContractPermissioningV2Transactions smartContractNodePermissioningV2;
private final NodeSmartContractPermissioningV2Conditions
nodeSmartContractPermissioningConditionsV2;
protected static final String CONTRACT_ADDRESS = "0x0000000000000000000000000000000000009999";
protected static final String GENESIS_FILE =
"/permissioning/simple_permissioning_v2_genesis.json";
protected final Cluster permissionedCluster;
protected NodeSmartContractPermissioningV2AcceptanceTestBase() {
super();
smartContractNodePermissioningV2 = new NodeSmartContractPermissioningV2Transactions(accounts);
nodeSmartContractPermissioningConditionsV2 =
new NodeSmartContractPermissioningV2Conditions(smartContractNodePermissioningV2);
this.permissionedCluster = permissionedCluster();
}
private Cluster permissionedCluster() {
final ClusterConfiguration clusterConfiguration =
new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build();
return new Cluster(clusterConfiguration, net);
}
protected Node permissionedNode(final String name, final Node... localConfigAllowedNodes) {
return permissionedNode(name, GENESIS_FILE, localConfigAllowedNodes);
}
protected Node permissionedNode(
final String name, final String genesisFile, final Node... localConfigAllowedNodes) {
PermissionedNodeBuilder permissionedNodeBuilder =
this.permissionedNodeBuilder
.name(name)
.genesisFile(genesisFile)
.nodesContractV2Enabled(CONTRACT_ADDRESS);
if (localConfigAllowedNodes != null && localConfigAllowedNodes.length > 0) {
permissionedNodeBuilder.nodesPermittedInConfig(localConfigAllowedNodes);
}
return permissionedNodeBuilder.build();
}
protected Node bootnode(final String name) {
return bootnode(name, GENESIS_FILE);
}
protected Node bootnode(final String name, final String genesisFile) {
try {
return besu.createCustomGenesisNode(name, genesisFile, true);
} catch (IOException e) {
throw new RuntimeException("Error creating node", e);
}
}
protected Node node(final String name) {
try {
return besu.createCustomGenesisNode(name, GENESIS_FILE, false);
} catch (IOException e) {
throw new RuntimeException("Error creating node", e);
}
}
@AfterEach
@Override
public void tearDownAcceptanceTestBase() {
permissionedCluster.stop();
super.tearDownAcceptanceTestBase();
}
protected Transaction<Hash> allowNode(final Node node) {
return smartContractNodePermissioningV2.allowNode(CONTRACT_ADDRESS, node);
}
protected Transaction<Hash> allowNode(final EnodeURL enodeURL) {
return smartContractNodePermissioningV2.allowNode(CONTRACT_ADDRESS, enodeURL);
}
protected Transaction<Hash> forbidNode(final Node node) {
return smartContractNodePermissioningV2.forbidNode(CONTRACT_ADDRESS, node);
}
protected Transaction<Hash> forbidNode(final EnodeURL enodeURL) {
return smartContractNodePermissioningV2.forbidNode(CONTRACT_ADDRESS, enodeURL);
}
protected Condition connectionIsForbidden(final Node node) {
return nodeSmartContractPermissioningConditionsV2.connectionIsForbidden(CONTRACT_ADDRESS, node);
}
protected Condition connectionIsForbidden(final EnodeURL enodeURL) {
return nodeSmartContractPermissioningConditionsV2.connectionIsForbidden(
CONTRACT_ADDRESS, enodeURL);
}
protected Condition connectionIsAllowed(final Node node) {
return nodeSmartContractPermissioningConditionsV2.connectionIsAllowed(CONTRACT_ADDRESS, node);
}
protected Condition connectionIsAllowed(final EnodeURL enodeURL) {
return nodeSmartContractPermissioningConditionsV2.connectionIsAllowed(
CONTRACT_ADDRESS, enodeURL);
}
}

View File

@@ -1,107 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.p2p.peers.ImmutableEnodeDnsConfiguration;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@Disabled("test is flaky #7191")
public class NodeSmartContractPermissioningV2DNSAcceptanceTest
extends NodeSmartContractPermissioningV2AcceptanceTestBase {
private Node bootnode;
private Node permissionedNode;
private Node allowedNode;
private Node forbiddenNode;
final ImmutableEnodeDnsConfiguration enodeDnsConfiguration =
ImmutableEnodeDnsConfiguration.builder().dnsEnabled(true).updateEnabled(true).build();
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");
allowedNode = node("allowed-node");
permissionedNode = permissionedNode("permissioned-node");
permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode);
// updating permissioning smart contract with allowed nodes
permissionedNode.execute(allowNode(bootnode));
permissionedNode.verify(connectionIsAllowed(bootnode));
permissionedNode.execute(allowNode(allowedNode));
permissionedNode.verify(connectionIsAllowed(allowedNode));
permissionedNode.execute(allowNode(permissionedNode));
permissionedNode.verify(connectionIsAllowed(permissionedNode));
}
@Test
public void permissionedNodeShouldAddDnsRuleAndAllowNode() throws UnknownHostException {
final EnodeURL forbiddenEnodeURL = getForbiddenEnodeURL();
Assertions.assertThat(forbiddenEnodeURL.toURI().getHost()).isEqualTo("127.0.0.1");
final EnodeURL forbiddenDnsEnodeURL = buildDnsEnodeUrl(forbiddenEnodeURL);
Assertions.assertThat(forbiddenDnsEnodeURL.toURI().getHost())
.isEqualTo(InetAddress.getLocalHost().getHostName());
permissionedNode.verify(connectionIsForbidden(forbiddenNode));
permissionedNode.verify(connectionIsForbidden(forbiddenDnsEnodeURL));
permissionedNode.execute(allowNode(forbiddenDnsEnodeURL));
permissionedNode.verify(connectionIsAllowed(forbiddenDnsEnodeURL));
permissionedNode.execute(forbidNode(forbiddenEnodeURL));
}
@Test
public void permissionedNodeShouldAddDNSRuleAndConnectToNewPeer() throws UnknownHostException {
final EnodeURL forbiddenEnodeURL = getForbiddenEnodeURL();
Assertions.assertThat(forbiddenEnodeURL.toURI().getHost()).isEqualTo("127.0.0.1");
final EnodeURL forbiddenDnsEnodeURL = buildDnsEnodeUrl(forbiddenEnodeURL);
Assertions.assertThat(forbiddenDnsEnodeURL.toURI().getHost())
.isEqualTo(InetAddress.getLocalHost().getHostName());
permissionedNode.verify(net.awaitPeerCount(2));
permissionedNode.verify(connectionIsForbidden(forbiddenNode));
permissionedNode.verify(connectionIsForbidden(forbiddenDnsEnodeURL));
permissionedNode.execute(allowNode(forbiddenDnsEnodeURL));
permissionedNode.verify(connectionIsAllowed(forbiddenDnsEnodeURL));
permissionedNode.verify(admin.addPeer(forbiddenNode));
permissionedNode.verify(net.awaitPeerCount(3));
permissionedNode.execute(forbidNode(forbiddenEnodeURL));
}
private EnodeURL getForbiddenEnodeURL() {
return EnodeURLImpl.fromURI(((RunnableNode) forbiddenNode).enodeUrl());
}
private EnodeURL buildDnsEnodeUrl(final EnodeURL forbiddenEnodeURL) {
return EnodeURLImpl.builder()
.configureFromEnode(forbiddenEnodeURL)
.ipAddress("localhost", enodeDnsConfiguration)
.build();
}
}

View File

@@ -1,85 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.permissioning;
import static java.util.stream.Collectors.toList;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@Disabled("flaky test #7155")
public class NodesSmartContractPermissioningStaticNodesAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
private Node miner;
private Node permissionedNode;
@BeforeEach
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, 25);
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, 25);
// 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();
}
@Nonnull
private List<String> mapNodesToEnodeURLs(final List<Node> staticNodes) {
return staticNodes.stream()
.map(node -> (RunnableNode) node)
.map(RunnableNode::enodeUrl)
.map(URI::toASCIIString)
.collect(toList());
}
}

View File

@@ -1,286 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.permissioning;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.config.GenesisConfig;
import org.hyperledger.besu.config.JsonUtil;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.chain.GenesisState;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import java.io.IOException;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.io.Resources;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class NodeSmartContractPermissioningControllerTest {
@Mock private MetricsSystem metricsSystem;
@Mock private Counter checkCounter;
@Mock private Counter checkPermittedCounter;
@Mock private Counter checkUnpermittedCounter;
private NodeSmartContractPermissioningController setupController(
final String resourceName, final String contractAddressString) throws IOException {
final ProtocolSchedule protocolSchedule = ProtocolScheduleFixture.MAINNET;
final String emptyContractFile =
Resources.toString(this.getClass().getResource(resourceName), UTF_8);
final ObjectNode jsonData = JsonUtil.objectNodeFromString(emptyContractFile, true);
final GenesisState genesisState =
GenesisState.fromConfig(GenesisConfig.fromConfig(jsonData), protocolSchedule);
final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock());
final WorldStateArchive worldArchive = createInMemoryWorldStateArchive();
genesisState.writeStateTo(worldArchive.getWorldState());
final TransactionSimulator ts =
new TransactionSimulator(
blockchain, worldArchive, protocolSchedule, MiningConfiguration.newDefault(), 0L);
final Address contractAddress = Address.fromHexString(contractAddressString);
when(metricsSystem.createCounter(
BesuMetricCategory.PERMISSIONING,
"node_smart_contract_check_count",
"Number of times the node smart contract permissioning provider has been checked"))
.thenReturn(checkCounter);
when(metricsSystem.createCounter(
BesuMetricCategory.PERMISSIONING,
"node_smart_contract_check_count_permitted",
"Number of times the node smart contract permissioning provider has been checked and returned permitted"))
.thenReturn(checkPermittedCounter);
when(metricsSystem.createCounter(
BesuMetricCategory.PERMISSIONING,
"node_smart_contract_check_count_unpermitted",
"Number of times the node smart contract permissioning provider has been checked and returned unpermitted"))
.thenReturn(checkUnpermittedCounter);
return new NodeSmartContractPermissioningController(contractAddress, ts, metricsSystem);
}
private void verifyCountersUntouched() {
verify(checkCounter, times(0)).inc();
verify(checkPermittedCounter, times(0)).inc();
verify(checkUnpermittedCounter, times(0)).inc();
}
private void verifyCountersPermitted() {
verify(checkCounter, times(1)).inc();
verify(checkPermittedCounter, times(1)).inc();
verify(checkUnpermittedCounter, times(0)).inc();
}
private void verifyCountersUnpermitted() {
verify(checkCounter, times(1)).inc();
verify(checkPermittedCounter, times(0)).inc();
verify(checkUnpermittedCounter, times(1)).inc();
}
private void verifyCountersFailedCheck() {
verify(checkCounter, times(1)).inc();
verify(checkPermittedCounter, times(0)).inc();
verify(checkUnpermittedCounter, times(0)).inc();
}
@Test
public void testIpv4Included() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.1:30303"),
EnodeURLImpl.fromString(
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.1:30304")))
.isTrue();
verifyCountersPermitted();
}
@Test
public void testIpv4DestinationMissing() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.1:30303"),
EnodeURLImpl.fromString(
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.1:30305")))
.isFalse();
verifyCountersUnpermitted();
}
@Test
public void testIpv4SourceMissing() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.1:30302"),
EnodeURLImpl.fromString(
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.1:30304")))
.isFalse();
verifyCountersUnpermitted();
}
@Test
public void testIpv6Included() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab61@[1:2:3:4:5:6:7:8]:30303"),
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab62@[1:2:3:4:5:6:7:8]:30304")))
.isTrue();
verifyCountersPermitted();
}
@Test
public void testIpv6SourceMissing() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab63@[1:2:3:4:5:6:7:8]:30303"),
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab62@[1:2:3:4:5:6:7:8]:30304")))
.isFalse();
verifyCountersUnpermitted();
}
@Test
public void testIpv6DestinationMissing() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab61@[1:2:3:4:5:6:7:8]:30303"),
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab63@[1:2:3:4:5:6:7:8]:30304")))
.isFalse();
verifyCountersUnpermitted();
}
@Test
public void testPermissioningContractMissing() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/noSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThatThrownBy(
() ->
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab61@[1:2:3:4:5:6:7:8]:30303"),
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab63@[1:2:3:4:5:6:7:8]:30304")))
.isInstanceOf(IllegalStateException.class)
.hasMessage("Permissioning contract does not exist");
verifyCountersFailedCheck();
}
@Test
public void testPermissioningContractCorrupt() throws IOException {
final NodeSmartContractPermissioningController controller =
setupController(
"/NodeSmartContractPermissioningControllerTest/corruptSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThatThrownBy(
() ->
controller.isConnectionPermitted(
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab61@[1:2:3:4:5:6:7:8]:30303"),
EnodeURLImpl.fromString(
"enode://1234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab63@[1:2:3:4:5:6:7:8]:30304")))
.isInstanceOf(IllegalStateException.class)
.hasMessage("Permissioning transaction failed when processing");
verifyCountersFailedCheck();
}
}

View File

@@ -1,226 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.permissioning;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.data.EnodeURL;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodeSmartContractV2PermissioningControllerTest {
/*
Payloads created using Remix to call method connectionAllowed(string, string, uint16)
*/
private static final Bytes SOURCE_ENODE_EXPECTED_PAYLOAD_IP =
Bytes.fromHexString(
"0x45a59e5b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000765f0000000000000000000000000000000000000000000000000000000000000080666362653966383332313834383762336330623530383738313933383830653663323563666438363730386330613062663063613931663063653633333734366138393266653234306166613562396138383062386263613438653861323237303465663933376664646132643763633633653464343165643162343137616500000000000000000000000000000000000000000000000000000000000000093132372e302e302e310000000000000000000000000000000000000000000000");
private static final Bytes DESTINATION_ENODE_EXPECTED_PAYLOAD_IP =
Bytes.fromHexString(
"0x45a59e5b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009dd40000000000000000000000000000000000000000000000000000000000000080333534386338376239393230666631366161346264636630316338356632353131376132396165313537346437353962616434386363393436336438653966376333633164316539666230643238653733383938393531663930653032373134616262373730666436643232653930333731383832613435363538383030653900000000000000000000000000000000000000000000000000000000000000093132372e302e302e310000000000000000000000000000000000000000000000");
private static final EnodeURL SOURCE_ENODE_IPV4 =
EnodeURLImpl.fromString(
"enode://fcbe9f83218487b3c0b50878193880e6c25cfd86708c0a0bf0ca91f0ce633746a892fe240afa5b9a880b8bca48e8a22704ef937fdda2d7cc63e4d41ed1b417ae@127.0.0.1:30303");
private static final EnodeURL DESTINATION_ENODE_IPV4 =
EnodeURLImpl.fromString(
"enode://3548c87b9920ff16aa4bdcf01c85f25117a29ae1574d759bad48cc9463d8e9f7c3c1d1e9fb0d28e73898951f90e02714abb770fd6d22e90371882a45658800e9@127.0.0.1:40404");
private static final EnodeURL SOURCE_ENODE_IPV6 =
EnodeURLImpl.fromString(
"enode://fcbe9f83218487b3c0b50878193880e6c25cfd86708c0a0bf0ca91f0ce633746a892fe240afa5b9a880b8bca48e8a22704ef937fdda2d7cc63e4d41ed1b417ae@[::ffff:7f00:0001]:30303");
private static final EnodeURL DESTINATION_ENODE_IPV6 =
EnodeURLImpl.fromString(
"enode://3548c87b9920ff16aa4bdcf01c85f25117a29ae1574d759bad48cc9463d8e9f7c3c1d1e9fb0d28e73898951f90e02714abb770fd6d22e90371882a45658800e9@[::ffff:7f00:0001]:40404");
private final BlockDataGenerator blockDataGenerator = new BlockDataGenerator();
private final Address contractAddress = Address.ZERO;
private final TransactionSimulator transactionSimulator = mock(TransactionSimulator.class);
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private NodeSmartContractV2PermissioningController permissioningController;
@BeforeEach
public void beforeEach() {
permissioningController =
new NodeSmartContractV2PermissioningController(
contractAddress, transactionSimulator, metricsSystem);
}
@Test
public void nonExpectedCallOutputThrowsIllegalState() {
final TransactionSimulatorResult txSimulatorResult =
transactionSimulatorResult(Bytes.random(10), ValidationResult.valid());
when(transactionSimulator.processAtHead(eq(callParams(SOURCE_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResult));
assertThatIllegalStateException()
.isThrownBy(
() ->
permissioningController.checkSmartContractRules(
SOURCE_ENODE_IPV4, DESTINATION_ENODE_IPV4));
}
@Test
public void falseCallOutputReturnsNotPermitted() {
final TransactionSimulatorResult txSimulatorResult =
transactionSimulatorResult(
NodeSmartContractV2PermissioningController.FALSE_RESPONSE, ValidationResult.valid());
when(transactionSimulator.processAtHead(eq(callParams(SOURCE_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResult));
boolean isPermitted =
permissioningController.checkSmartContractRules(SOURCE_ENODE_IPV4, DESTINATION_ENODE_IPV4);
assertThat(isPermitted).isFalse();
}
@Test
public void failedCallOutputReturnsNotPermitted() {
final TransactionSimulatorResult txSimulatorResult =
transactionSimulatorResult(
NodeSmartContractV2PermissioningController.TRUE_RESPONSE,
ValidationResult.invalid(TransactionInvalidReason.INTERNAL_ERROR));
when(transactionSimulator.processAtHead(eq(callParams(SOURCE_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResult));
boolean isPermitted =
permissioningController.checkSmartContractRules(SOURCE_ENODE_IPV4, DESTINATION_ENODE_IPV4);
assertThat(isPermitted).isFalse();
}
@Test
public void expectedPayloadWhenCheckingPermissioningWithIPV4() {
final TransactionSimulatorResult txSimulatorResult =
transactionSimulatorResult(
NodeSmartContractV2PermissioningController.TRUE_RESPONSE, ValidationResult.valid());
when(transactionSimulator.processAtHead(eq(callParams(SOURCE_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResult));
when(transactionSimulator.processAtHead(eq(callParams(DESTINATION_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResult));
boolean isPermitted =
permissioningController.checkSmartContractRules(SOURCE_ENODE_IPV4, DESTINATION_ENODE_IPV4);
assertThat(isPermitted).isTrue();
verify(transactionSimulator, times(2)).processAtHead(any());
}
@Test
public void expectedPayloadWhenCheckingPermissioningWithIPV6() {
final TransactionSimulatorResult txSimulatorResult =
transactionSimulatorResult(
NodeSmartContractV2PermissioningController.TRUE_RESPONSE, ValidationResult.valid());
when(transactionSimulator.processAtHead(eq(callParams(SOURCE_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResult));
when(transactionSimulator.processAtHead(eq(callParams(DESTINATION_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResult));
boolean isPermitted =
permissioningController.checkSmartContractRules(SOURCE_ENODE_IPV6, DESTINATION_ENODE_IPV6);
assertThat(isPermitted).isTrue();
verify(transactionSimulator, times(2)).processAtHead(any());
}
@Test
public void expectedPayloadWhenCheckingPermissioningWithAlternateDNS()
throws UnknownHostException {
final TransactionSimulatorResult txSimulatorResultFalse =
transactionSimulatorResult(
NodeSmartContractV2PermissioningController.FALSE_RESPONSE, ValidationResult.valid());
final TransactionSimulatorResult txSimulatorResultTrue =
transactionSimulatorResult(
NodeSmartContractV2PermissioningController.TRUE_RESPONSE, ValidationResult.valid());
when(transactionSimulator.processAtHead(eq(callParams(SOURCE_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResultFalse));
when(transactionSimulator.processAtHead(eq(callParams(DESTINATION_ENODE_EXPECTED_PAYLOAD_IP))))
.thenReturn(Optional.of(txSimulatorResultFalse));
var sourcePayload = sourceEnodeExpectedPayloadDns();
when(transactionSimulator.processAtHead(eq(callParams(Bytes.fromHexString(sourcePayload)))))
.thenReturn(Optional.of(txSimulatorResultTrue));
var destinationPayload = destinationEnodeExpectedPayloadDns();
when(transactionSimulator.processAtHead(
eq(callParams(Bytes.fromHexString(destinationPayload)))))
.thenReturn(Optional.of(txSimulatorResultTrue));
boolean isPermitted =
permissioningController.checkSmartContractRules(SOURCE_ENODE_IPV4, DESTINATION_ENODE_IPV4);
assertThat(isPermitted).isTrue();
verify(transactionSimulator, times(4)).processAtHead(any());
}
private CallParameter callParams(final Bytes payload) {
return new CallParameter(null, contractAddress, -1, null, null, payload);
}
private TransactionSimulatorResult transactionSimulatorResult(
final Bytes output, final ValidationResult<TransactionInvalidReason> validationResult) {
return new TransactionSimulatorResult(
blockDataGenerator.transaction(),
TransactionProcessingResult.successful(
blockDataGenerator.logs(1, 1), 0L, 0L, output, validationResult));
}
// Note - don't use FunctionEncoder.makeFunction here otherwise we're not really testing anything!
private String sourceEnodeExpectedPayloadDns() throws UnknownHostException {
var hostname = InetAddress.getLocalHost().getHostName();
return "0x45a59e5b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000765f0000000000000000000000000000000000000000000000000000000000000080666362653966383332313834383762336330623530383738313933383830653663323563666438363730386330613062663063613931663063653633333734366138393266653234306166613562396138383062386263613438653861323237303465663933376664646132643763633633653464343165643162343137616500000000000000000000000000000000000000000000000000000000000000"
+ Bytes.of(hostname.length()).toUnprefixedHexString()
+ Bytes.of(hostname.getBytes(UTF_8)).toUnprefixedHexString()
+ "00".repeat(32 - hostname.length());
}
private String destinationEnodeExpectedPayloadDns() throws UnknownHostException {
var hostname = InetAddress.getLocalHost().getHostName();
return "0x45a59e5b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000009dd40000000000000000000000000000000000000000000000000000000000000080333534386338376239393230666631366161346264636630316338356632353131376132396165313537346437353962616434386363393436336438653966376333633164316539666230643238653733383938393531663930653032373134616262373730666436643232653930333731383832613435363538383030653900000000000000000000000000000000000000000000000000000000000000"
+ Bytes.of(hostname.length()).toUnprefixedHexString()
+ Bytes.of(hostname.getBytes(UTF_8)).toUnprefixedHexString()
+ "00".repeat(32 - hostname.length());
}
}

View File

@@ -1,197 +0,0 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.permissioning;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.config.GenesisConfig;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.chain.GenesisState;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import java.io.IOException;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class TransactionSmartContractPermissioningControllerTest {
@Mock private MetricsSystem metricsSystem;
@Mock private Counter checkCounter;
@Mock private Counter checkPermittedCounter;
@Mock private Counter checkUnpermittedCounter;
private TransactionSmartContractPermissioningController setupController(
final String resourceName, final String contractAddressString) {
final ProtocolSchedule protocolSchedule = ProtocolScheduleFixture.MAINNET;
final GenesisState genesisState =
GenesisState.fromConfig(
GenesisConfig.fromSource(this.getClass().getResource(resourceName)), protocolSchedule);
final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock());
final WorldStateArchive worldArchive = createInMemoryWorldStateArchive();
genesisState.writeStateTo(worldArchive.getWorldState());
final TransactionSimulator ts =
new TransactionSimulator(
blockchain, worldArchive, protocolSchedule, MiningConfiguration.newDefault(), 0L);
final Address contractAddress = Address.fromHexString(contractAddressString);
when(metricsSystem.createCounter(
BesuMetricCategory.PERMISSIONING,
"transaction_smart_contract_check_count",
"Number of times the transaction smart contract permissioning provider has been checked"))
.thenReturn(checkCounter);
when(metricsSystem.createCounter(
BesuMetricCategory.PERMISSIONING,
"transaction_smart_contract_check_count_permitted",
"Number of times the transaction smart contract permissioning provider has been checked and returned permitted"))
.thenReturn(checkPermittedCounter);
when(metricsSystem.createCounter(
BesuMetricCategory.PERMISSIONING,
"transaction_smart_contract_check_count_unpermitted",
"Number of times the transaction smart contract permissioning provider has been checked and returned unpermitted"))
.thenReturn(checkUnpermittedCounter);
return new TransactionSmartContractPermissioningController(contractAddress, ts, metricsSystem);
}
private Transaction transactionForAccount(final Address address) {
return Transaction.builder()
.type(TransactionType.FRONTIER)
.sender(address)
.value(Wei.ZERO)
.gasPrice(Wei.ZERO)
.gasLimit(0)
.payload(Bytes.fromHexString("0x1234"))
.nonce(1)
.signature(
SignatureAlgorithmFactory.getInstance()
.createSignature(BigInteger.ONE, BigInteger.TEN, (byte) 1))
.build();
}
private void verifyCountersUntouched() {
verify(checkCounter, times(0)).inc();
verify(checkPermittedCounter, times(0)).inc();
verify(checkUnpermittedCounter, times(0)).inc();
}
private void verifyCountersPermitted() {
verify(checkCounter, times(1)).inc();
verify(checkPermittedCounter, times(1)).inc();
verify(checkUnpermittedCounter, times(0)).inc();
}
private void verifyCountersUnpermitted() {
verify(checkCounter, times(1)).inc();
verify(checkPermittedCounter, times(0)).inc();
verify(checkUnpermittedCounter, times(1)).inc();
}
private void verifyCountersFailedCheck() {
verify(checkCounter, times(1)).inc();
verify(checkPermittedCounter, times(0)).inc();
verify(checkUnpermittedCounter, times(0)).inc();
}
@Test
public void testAccountIncluded() throws IOException {
final TransactionSmartContractPermissioningController controller =
setupController(
"/TransactionSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(controller.isPermitted(transactionForAccount(Address.fromHexString("0x1"))))
.isTrue();
verifyCountersPermitted();
}
@Test
public void testAccountNotIncluded() throws IOException {
final TransactionSmartContractPermissioningController controller =
setupController(
"/TransactionSmartContractPermissioningControllerTest/preseededSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(controller.isPermitted(transactionForAccount(Address.fromHexString("0x2"))))
.isFalse();
verifyCountersUnpermitted();
}
@Test
public void testPermissioningContractMissing() throws IOException {
final TransactionSmartContractPermissioningController controller =
setupController(
"/TransactionSmartContractPermissioningControllerTest/noSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThat(controller.isPermitted(transactionForAccount(Address.fromHexString("0x1"))))
.isTrue();
verifyCountersPermitted();
}
@Test
public void testPermissioningContractCorrupt() throws IOException {
final TransactionSmartContractPermissioningController controller =
setupController(
"/TransactionSmartContractPermissioningControllerTest/corruptSmartPermissioning.json",
"0x0000000000000000000000000000000000001234");
verifyCountersUntouched();
assertThatThrownBy(
() -> controller.isPermitted(transactionForAccount(Address.fromHexString("0x1"))))
.isInstanceOf(IllegalStateException.class)
.hasMessage("Transaction permissioning transaction failed when processing");
verifyCountersFailedCheck();
}
}