BFT acceptance tests for Berlin and London (#5294)

Signed-off-by: Jason Frame <jason.frame@consensys.net>
pull/5313/head
Jason Frame 2 years ago committed by GitHub
parent b5a5bded90
commit e1da8ee6c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/blockchain/Amount.java
  2. 6
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java
  3. 1
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java
  4. 80
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/AccountTransactions.java
  5. 30
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransaction.java
  6. 39
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransactionBuilder.java
  7. 103
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftMiningAcceptanceTest.java
  8. 2
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/jsonrpc/EthSendRawTransactionTest.java
  9. 5
      acceptance-tests/tests/src/test/resources/ibft/ibft.json
  10. 2
      acceptance-tests/tests/src/test/resources/qbft/qbft.json

@ -28,6 +28,8 @@ public class Amount {
private final BigDecimal value;
private final Unit unit;
public static Amount ZERO = new Amount(BigDecimal.ZERO, WEI);
private Amount(final BigDecimal value, final Unit unit) {
this.value = value;
this.unit = unit;

@ -98,7 +98,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
private final boolean revertReasonEnabled;
private final String name;
private final MiningParameters miningParameters;
private MiningParameters miningParameters;
private final List<String> runCommand;
private PrivacyParameters privacyParameters = PrivacyParameters.DEFAULT;
private final JsonRpcConfiguration jsonRpcConfiguration;
@ -661,6 +661,10 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
return miningParameters;
}
public void setMiningParameters(final MiningParameters miningParameters) {
this.miningParameters = miningParameters;
}
public PrivacyParameters getPrivacyParameters() {
return privacyParameters;
}

@ -116,6 +116,7 @@ public class BesuNodeConfigurationBuilder {
this.miningParameters =
new MiningParameters.Builder()
.miningEnabled(enabled)
.minTransactionGasPrice(Wei.of(1000))
.coinbase(AddressHelpers.ofValue(1))
.build();
this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER.name());

@ -15,6 +15,7 @@
package org.hyperledger.besu.tests.acceptance.dsl.transaction.account;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.plugin.data.TransactionType;
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.blockchain.Amount;
@ -37,16 +38,16 @@ public class AccountTransactions {
}
public TransferTransaction createTransfer(
final Account recipient, final int amount, final SignatureAlgorithm signatureAlgorithm) {
return createBuilder(accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount))
.setSignatureAlgorithm(signatureAlgorithm)
final Account recipient, final int amount, final Amount gasPrice) {
return createFrontierBuilder(accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount))
.gasPrice(gasPrice)
.build();
}
public TransferTransaction createTransfer(
final Account recipient, final int amount, final long chainId) {
return createBuilder(accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount))
.chainId(chainId)
final Account recipient, final int amount, final SignatureAlgorithm signatureAlgorithm) {
return createFrontierBuilder(accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount))
.setSignatureAlgorithm(signatureAlgorithm)
.build();
}
@ -56,24 +57,44 @@ public class AccountTransactions {
public TransferTransaction createTransfer(
final Account sender, final Account recipient, final int amount) {
return createBuilder(sender, recipient, Amount.ether(amount)).build();
return createFrontierBuilder(sender, recipient, Amount.ether(amount)).build();
}
public TransferTransaction createTransfer(
final Account sender, final Account recipient, final Amount amount) {
return createBuilder(sender, recipient, amount).build();
return createFrontierBuilder(sender, recipient, amount).build();
}
public TransferTransaction createTransfer(
final Account sender, final Account recipient, final int amount, final BigInteger nonce) {
return createBuilder(sender, recipient, Amount.ether(amount)).nonce(nonce).build();
return createFrontierBuilder(sender, recipient, Amount.ether(amount)).nonce(nonce).build();
}
public TransferTransaction create1559Transfer(
final Account recipient, final int amount, final long chainId) {
return create1559Builder(
accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount), chainId)
.build();
}
public TransferTransaction create1559Transfer(
final Account recipient, final int amount, final long chainId, final Amount gasPrice) {
return create1559Builder(
accounts.getPrimaryBenefactor(), recipient, Amount.ether(amount), chainId)
.gasPrice(gasPrice)
.build();
}
public TransferTransactionSet createIncrementalTransfers(
final Account sender, final Account recipient, final int etherAmount) {
return createIncrementalTransfers(sender, recipient, etherAmount, DEFAULT_GAS_PRICE);
}
public TransferTransactionSet createIncrementalTransfers(
final Account sender, final Account recipient, final int etherAmount, final Amount gasPrice) {
final List<TransferTransaction> transfers = new ArrayList<>();
final TransferTransactionBuilder transferOneEther =
createBuilder(sender, recipient, Amount.ether(1));
createFrontierBuilder(sender, recipient, Amount.ether(1)).gasPrice(gasPrice);
for (int i = 1; i <= etherAmount; i++) {
transfers.add(transferOneEther.build());
@ -82,12 +103,47 @@ public class AccountTransactions {
return new TransferTransactionSet(transfers);
}
private TransferTransactionBuilder createBuilder(
public TransferTransactionSet create1559IncrementalTransfers(
final Account sender, final Account recipient, final int etherAmount, final long chainId) {
return create1559IncrementalTransfers(
sender, recipient, etherAmount, chainId, DEFAULT_GAS_PRICE);
}
public TransferTransactionSet create1559IncrementalTransfers(
final Account sender,
final Account recipient,
final int etherAmount,
final long chainId,
final Amount gasPrice) {
final List<TransferTransaction> transfers = new ArrayList<>();
final TransferTransactionBuilder transferOneEther =
create1559Builder(sender, recipient, Amount.ether(1), chainId).gasPrice(gasPrice);
for (int i = 1; i <= etherAmount; i++) {
transfers.add(transferOneEther.build());
}
return new TransferTransactionSet(transfers);
}
private TransferTransactionBuilder createFrontierBuilder(
final Account sender, final Account recipient, final Amount amount) {
return new TransferTransactionBuilder()
.sender(sender)
.recipient(recipient)
.amount(amount)
.gasPrice(DEFAULT_GAS_PRICE);
.gasPrice(DEFAULT_GAS_PRICE)
.transactionType(TransactionType.FRONTIER);
}
private TransferTransactionBuilder create1559Builder(
final Account sender, final Account recipient, final Amount amount, final long chainId) {
return new TransferTransactionBuilder()
.sender(sender)
.recipient(recipient)
.amount(amount)
.gasPrice(DEFAULT_GAS_PRICE)
.chainId(chainId)
.transactionType(TransactionType.EIP1559);
}
}

@ -16,6 +16,7 @@ package org.hyperledger.besu.tests.acceptance.dsl.transaction.account;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
@ -49,6 +50,7 @@ public class TransferTransaction implements Transaction<Hash> {
private final BigInteger nonce;
private final Optional<BigInteger> chainId;
private final SignatureAlgorithm signatureAlgorithm;
private final TransactionType transactionType;
private byte[] signedTxData = null;
public TransferTransaction(
@ -58,7 +60,8 @@ public class TransferTransaction implements Transaction<Hash> {
final Amount gasPrice,
final BigInteger nonce,
final Optional<BigInteger> chainId,
final SignatureAlgorithm signatureAlgorithm) {
final SignatureAlgorithm signatureAlgorithm,
final TransactionType transactionType) {
this.sender = sender;
this.recipient = recipient;
this.transferAmount = transferAmount.getValue();
@ -67,6 +70,7 @@ public class TransferTransaction implements Transaction<Hash> {
this.nonce = nonce;
this.chainId = chainId;
this.signatureAlgorithm = signatureAlgorithm;
this.transactionType = transactionType;
}
@Override
@ -116,26 +120,16 @@ public class TransferTransaction implements Transaction<Hash> {
}
private BigInteger convertGasPriceToWei(final Amount unconverted) {
final BigInteger price =
Convert.toWei(unconverted.getValue(), unconverted.getUnit()).toBigInteger();
if (MINIMUM_GAS_PRICE.compareTo(price) > 0) {
throw new IllegalArgumentException(
String.format(
"Gas price: %s WEI, is below the accepted minimum: %s WEI",
price, MINIMUM_GAS_PRICE));
}
return price;
return Convert.toWei(unconverted.getValue(), unconverted.getUnit()).toBigInteger();
}
private RawTransaction createRawTransaction() {
return chainId
.map(this::createTransactionWithChainId)
.orElseGet(this::createTransactionWithoutChainId);
return transactionType == TransactionType.FRONTIER
? createFrontierTransaction()
: create1559Transaction(chainId.orElseThrow());
}
private RawTransaction createTransactionWithoutChainId() {
private RawTransaction createFrontierTransaction() {
return RawTransaction.createEtherTransaction(
getNonce(),
gasPrice,
@ -144,14 +138,14 @@ public class TransferTransaction implements Transaction<Hash> {
Convert.toWei(transferAmount, transferUnit).toBigIntegerExact());
}
private RawTransaction createTransactionWithChainId(final BigInteger chainId) {
private RawTransaction create1559Transaction(final BigInteger chainId) {
return RawTransaction.createEtherTransaction(
chainId.longValueExact(),
getNonce(),
INTRINSIC_GAS,
recipient.getAddress(),
Convert.toWei(transferAmount, transferUnit).toBigIntegerExact(),
BigInteger.ONE,
BigInteger.ZERO,
gasPrice);
}
}

@ -18,6 +18,7 @@ import static org.testcontainers.shaded.com.google.common.base.Preconditions.che
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount;
@ -34,6 +35,8 @@ public class TransferTransactionBuilder {
private Optional<BigInteger> chainId = Optional.empty();
private SignatureAlgorithm signatureAlgorithm = new SECP256K1();
private TransactionType transactionType;
public TransferTransactionBuilder sender(final Account sender) {
this.sender = sender;
validateSender();
@ -68,13 +71,6 @@ public class TransferTransactionBuilder {
return this;
}
public TransferTransaction build() {
validateSender();
validateTransferAmount();
return new TransferTransaction(
sender, recipient, transferAmount, gasPrice, nonce, chainId, signatureAlgorithm);
}
public TransferTransactionBuilder chainId(final BigInteger chainId) {
this.chainId = Optional.ofNullable(chainId);
return this;
@ -85,6 +81,26 @@ public class TransferTransactionBuilder {
return chainId(BigInteger.valueOf(chainId));
}
public TransferTransactionBuilder transactionType(final TransactionType transactionType) {
this.transactionType = transactionType;
return this;
}
public TransferTransaction build() {
validateSender();
validateTransferAmount();
validateTransactionType();
return new TransferTransaction(
sender,
recipient,
transferAmount,
gasPrice,
nonce,
chainId,
signatureAlgorithm,
transactionType);
}
private void validateSender() {
if (sender == null) {
throw new IllegalArgumentException("NULL sender is not allowed.");
@ -96,4 +112,13 @@ public class TransferTransactionBuilder {
throw new IllegalArgumentException("NULL transferAmount is not allowed.");
}
}
private void validateTransactionType() {
if (transactionType == null) {
throw new IllegalArgumentException("NULL transactionType is not allowed.");
}
if (transactionType == TransactionType.EIP1559 && chainId.isEmpty()) {
throw new IllegalStateException("Chain ID must be specified for EIP-1559 transactions");
}
}
}

@ -14,11 +14,18 @@
*/
package org.hyperledger.besu.tests.acceptance.bft;
import org.hyperledger.besu.config.JsonUtil;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import java.util.List;
import java.util.Optional;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;
public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
@ -29,7 +36,7 @@ public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
}
@Test
public void shouldMineOnSingleNode() throws Exception {
public void shouldMineOnSingleNodeWithPaidGas_Berlin() throws Exception {
final BesuNode minerNode = nodeFactory.createNode(besu, "miner1");
cluster.start(minerNode);
@ -48,6 +55,88 @@ public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
cluster.verify(receiver.balanceEquals(3));
}
@Test
public void shouldMineOnSingleNodeWithFreeGas_Berlin() throws Exception {
final BesuNode minerNode = nodeFactory.createNode(besu, "miner1");
final MiningParameters zeroGasMiningParams =
new MiningParameters.Builder()
.miningEnabled(true)
.minTransactionGasPrice(Wei.ZERO)
.coinbase(AddressHelpers.ofValue(1))
.build();
minerNode.setMiningParameters(zeroGasMiningParams);
cluster.start(minerNode);
cluster.verify(blockchain.reachesHeight(minerNode, 1));
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO));
cluster.verify(sender.balanceEquals(50));
minerNode.execute(
accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO));
cluster.verify(receiver.balanceEquals(1));
minerNode.execute(
accountTransactions.createIncrementalTransfers(sender, receiver, 2, Amount.ZERO));
cluster.verify(receiver.balanceEquals(3));
}
@Test
public void shouldMineOnSingleNodeWithPaidGas_London() throws Exception {
final BesuNode minerNode = nodeFactory.createNode(besu, "miner1");
updateGenesisConfigToLondon(minerNode, false);
cluster.start(minerNode);
cluster.verify(blockchain.reachesHeight(minerNode, 1));
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode.execute(accountTransactions.createTransfer(sender, 50));
cluster.verify(sender.balanceEquals(50));
minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4));
cluster.verify(sender.balanceEquals(100));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1));
cluster.verify(receiver.balanceEquals(1));
minerNode.execute(accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4));
cluster.verify(receiver.balanceEquals(3));
}
@Test
public void shouldMineOnSingleNodeWithFreeGas_London() throws Exception {
final BesuNode minerNode = nodeFactory.createNode(besu, "miner1");
updateGenesisConfigToLondon(minerNode, true);
cluster.start(minerNode);
cluster.verify(blockchain.reachesHeight(minerNode, 1));
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO));
cluster.verify(sender.balanceEquals(50));
minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO));
cluster.verify(sender.balanceEquals(100));
minerNode.execute(
accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO));
cluster.verify(receiver.balanceEquals(1));
minerNode.execute(
accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO));
cluster.verify(receiver.balanceEquals(3));
}
@Test
public void shouldMineOnMultipleNodes() throws Exception {
final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1");
@ -123,4 +212,16 @@ public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
cluster.verifyOnActiveNodes(receiver.balanceEquals(80));
}
private static void updateGenesisConfigToLondon(
final BesuNode minerNode, final boolean zeroBaseFeeEnabled) {
final Optional<String> genesisConfig =
minerNode.getGenesisConfigProvider().create(List.of(minerNode));
final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow());
final ObjectNode config = (ObjectNode) genesisConfigNode.get("config");
config.remove("berlinBlock");
config.put("londonBlock", 0);
config.put("zeroBaseFee", zeroBaseFeeEnabled);
minerNode.setGenesisConfig(genesisConfigNode.toString());
}
}

@ -103,7 +103,7 @@ public class EthSendRawTransactionTest extends AcceptanceTestBase {
private TransferTransaction createTransaction(final boolean withChainId) {
if (withChainId) {
return accountTransactions.createTransfer(createAccount(), 2, CHAIN_ID);
return accountTransactions.create1559Transfer(createAccount(), 2, CHAIN_ID);
} else {
final BigInteger nonce =
miningNode.execute(ethTransactions.getTransactionCount(sender.getAddress()));

@ -1,10 +1,7 @@
{
"config": {
"chainId": 4,
"homesteadBlock": 1,
"eip150Block": 2,
"eip158Block": 3,
"byzantiumBlock": 1035301,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 1,
"epochlength": 30000,

@ -1,7 +1,7 @@
{
"config": {
"chainId": 4,
"byzantiumBlock": 0,
"berlinBlock": 0,
"qbft": {
"blockperiodseconds": 1,
"epochlength": 30000,

Loading…
Cancel
Save