mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 15:37:54 -05:00
Restructuring the DSL (#78)
* Restructuring the DSL Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
This commit is contained in:
@@ -39,8 +39,8 @@ public class CreateAccountAcceptanceTest extends AcceptanceTestBase {
|
||||
|
||||
@Test
|
||||
public void shouldCreateAnAccount() {
|
||||
final Account account = accounts.createAccount("account1", "20", ETHER, fullNode);
|
||||
accounts.waitForAccountBalance(account, "20", ETHER, minerNode);
|
||||
accounts.waitForAccountBalance(account, "20", ETHER, fullNode);
|
||||
final Account account = accounts.createAccount("a-new-account");
|
||||
minerNode.execute(transactions.createTransfer(account, 20));
|
||||
cluster.verify(account.balanceEquals("20", ETHER));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,17 +14,26 @@ package tech.pegasys.pantheon.tests.acceptance.dsl;
|
||||
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Accounts;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Cluster;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transactions;
|
||||
|
||||
import org.junit.After;
|
||||
|
||||
public class AcceptanceTestBase {
|
||||
|
||||
protected Cluster cluster = new Cluster();
|
||||
protected Accounts accounts = new Accounts();
|
||||
protected JsonRpc jsonRpc = new JsonRpc(cluster);
|
||||
protected final Accounts accounts;
|
||||
protected final Cluster cluster;
|
||||
protected final Transactions transactions;
|
||||
protected final JsonRpc jsonRpc;
|
||||
|
||||
protected AcceptanceTestBase() {
|
||||
accounts = new Accounts();
|
||||
cluster = new Cluster();
|
||||
transactions = new Transactions(accounts);
|
||||
jsonRpc = new JsonRpc(cluster);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDownAcceptanceTestBase() throws Exception {
|
||||
public void tearDownAcceptanceTestBase() {
|
||||
cluster.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,14 @@ import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
|
||||
import tech.pegasys.pantheon.crypto.SECP256K1.PrivateKey;
|
||||
import tech.pegasys.pantheon.ethereum.core.Address;
|
||||
import tech.pegasys.pantheon.ethereum.core.Hash;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.ExpectAccountBalance;
|
||||
import tech.pegasys.pantheon.util.bytes.Bytes32;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.web3j.crypto.Credentials;
|
||||
import org.web3j.utils.Convert.Unit;
|
||||
|
||||
public class Account {
|
||||
|
||||
@@ -61,4 +64,12 @@ public class Account {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Condition balanceEquals(final String expectedBalance, final Unit balanceUnit) {
|
||||
return new ExpectAccountBalance(this, expectedBalance, balanceUnit);
|
||||
}
|
||||
|
||||
public Condition balanceEquals(final int expectedBalance) {
|
||||
return balanceEquals(String.valueOf(expectedBalance), Unit.ETHER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,25 +12,8 @@
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.account;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.web3j.utils.Convert.Unit.ETHER;
|
||||
import static org.web3j.utils.Convert.toWei;
|
||||
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
|
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Hash;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.web3j.utils.Convert.Unit;
|
||||
|
||||
public class Accounts {
|
||||
|
||||
private static final Logger LOG = getLogger();
|
||||
|
||||
private final Account richBenefactorOne;
|
||||
private final Account richBenefactorTwo;
|
||||
|
||||
@@ -45,76 +28,15 @@ public class Accounts {
|
||||
"c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3");
|
||||
}
|
||||
|
||||
public Account createAccount(
|
||||
final String accountName,
|
||||
final String initialBalance,
|
||||
final Unit initialBalanceUnit,
|
||||
final PantheonNode createOnNode) {
|
||||
final Account account = Account.create(accountName);
|
||||
createOnNode.transferFunds(richBenefactorOne, account, initialBalance, initialBalanceUnit);
|
||||
public Account getSecondaryBenefactor() {
|
||||
return richBenefactorTwo;
|
||||
}
|
||||
|
||||
return account;
|
||||
public Account getPrimaryBenefactor() {
|
||||
return richBenefactorOne;
|
||||
}
|
||||
|
||||
public Account createAccount(final String accountName) {
|
||||
return Account.create(accountName);
|
||||
}
|
||||
|
||||
public void waitForAccountBalance(
|
||||
final Account account,
|
||||
final String expectedBalance,
|
||||
final Unit balanceUnit,
|
||||
final PantheonNode node) {
|
||||
LOG.info(
|
||||
"Waiting for {} to have a balance of {} {} on node {}",
|
||||
account.getName(),
|
||||
expectedBalance,
|
||||
balanceUnit,
|
||||
node.getName());
|
||||
|
||||
waitFor(
|
||||
() ->
|
||||
assertThat(node.getAccountBalance(account))
|
||||
.isEqualTo(toWei(expectedBalance, balanceUnit).toBigIntegerExact()));
|
||||
}
|
||||
|
||||
public void waitForAccountBalance(
|
||||
final Account account, final int etherAmount, final PantheonNode node) {
|
||||
waitForAccountBalance(account, String.valueOf(etherAmount), ETHER, node);
|
||||
}
|
||||
|
||||
public Hash transfer(final Account recipient, final int amount, final PantheonNode node) {
|
||||
return transfer(richBenefactorOne, recipient, amount, node);
|
||||
}
|
||||
|
||||
public Hash transfer(
|
||||
final Account sender, final Account recipient, final int amount, final PantheonNode node) {
|
||||
return node.transferFunds(sender, recipient, String.valueOf(amount), Unit.ETHER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer funds in separate transactions (1 eth increments). This is a strategy to increase the
|
||||
* total of transactions.
|
||||
*
|
||||
* @param fromAccount account sending the ether value
|
||||
* @param toAccount account receiving the ether value
|
||||
* @param etherAmount amount of ether to transfer
|
||||
* @return a list with the hashes of each transaction
|
||||
*/
|
||||
public List<Hash> incrementalTransfer(
|
||||
final Account fromAccount,
|
||||
final Account toAccount,
|
||||
final int etherAmount,
|
||||
final PantheonNode node) {
|
||||
final List<Hash> txHashes = new ArrayList<>();
|
||||
for (int i = 1; i <= etherAmount; i++) {
|
||||
final Hash hash = node.transferFunds(fromAccount, toAccount, String.valueOf(1), Unit.ETHER);
|
||||
txHashes.add(hash);
|
||||
}
|
||||
return txHashes;
|
||||
}
|
||||
|
||||
public Account getSecondaryBenefactor() {
|
||||
return richBenefactorTwo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2018 ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.condition;
|
||||
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node;
|
||||
|
||||
public interface Condition {
|
||||
|
||||
void verify(Node node);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2018 ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.condition;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.web3j.utils.Convert.toWei;
|
||||
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
|
||||
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node;
|
||||
|
||||
import org.web3j.utils.Convert.Unit;
|
||||
|
||||
public class ExpectAccountBalance implements Condition {
|
||||
|
||||
private final Account account;
|
||||
private final String expectedBalance;
|
||||
private final Unit balanceUnit;
|
||||
|
||||
public ExpectAccountBalance(
|
||||
final Account account, final String expectedBalance, final Unit balanceUnit) {
|
||||
this.expectedBalance = expectedBalance;
|
||||
this.balanceUnit = balanceUnit;
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(final Node node) {
|
||||
waitFor(
|
||||
() ->
|
||||
assertThat(node.getAccountBalance(account))
|
||||
.isEqualTo(toWei(expectedBalance, balanceUnit).toBigIntegerExact()));
|
||||
}
|
||||
}
|
||||
@@ -13,11 +13,9 @@
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.node;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.web3j.utils.Convert.toWei;
|
||||
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
|
||||
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -25,14 +23,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.web3j.utils.Convert.Unit;
|
||||
|
||||
public class Cluster implements AutoCloseable {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(Cluster.class);
|
||||
|
||||
private final Map<String, PantheonNode> nodes = new HashMap<>();
|
||||
private final PantheonNodeRunner pantheonNodeRunner = PantheonNodeRunner.instance();
|
||||
|
||||
@@ -90,25 +82,9 @@ public class Cluster implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
public void awaitPropagation(final Account account, final int expectedBalance) {
|
||||
awaitPropagation(account, String.valueOf(expectedBalance), Unit.ETHER);
|
||||
}
|
||||
|
||||
public void awaitPropagation(
|
||||
final Account account, final String expectedBalance, final Unit balanceUnit) {
|
||||
|
||||
for (final PantheonNode node : nodes.values()) {
|
||||
LOG.info(
|
||||
"Waiting for {} to have a balance of {} {} on node {}",
|
||||
account.getName(),
|
||||
expectedBalance,
|
||||
balanceUnit,
|
||||
node.getName());
|
||||
|
||||
waitFor(
|
||||
() ->
|
||||
assertThat(node.getAccountBalance(account))
|
||||
.isEqualTo(toWei(expectedBalance, balanceUnit).toBigIntegerExact()));
|
||||
public void verify(final Condition expected) {
|
||||
for (final Node node : nodes.values()) {
|
||||
expected.verify(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2018 ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.node;
|
||||
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public interface Node {
|
||||
|
||||
<T> T execute(Transaction<T> transaction);
|
||||
|
||||
BigInteger getAccountBalance(Account account);
|
||||
}
|
||||
@@ -16,15 +16,14 @@ import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
import static org.web3j.protocol.core.DefaultBlockParameterName.LATEST;
|
||||
import static org.web3j.utils.Numeric.toHexString;
|
||||
|
||||
import tech.pegasys.pantheon.controller.KeyPairUtil;
|
||||
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
|
||||
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
|
||||
import tech.pegasys.pantheon.ethereum.core.Hash;
|
||||
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
|
||||
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -44,23 +43,17 @@ import com.google.common.io.MoreFiles;
|
||||
import com.google.common.io.RecursiveDeleteOption;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.java_websocket.exceptions.WebsocketNotConnectedException;
|
||||
import org.web3j.crypto.RawTransaction;
|
||||
import org.web3j.crypto.TransactionEncoder;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.Web3jService;
|
||||
import org.web3j.protocol.core.methods.response.EthGetBalance;
|
||||
import org.web3j.protocol.http.HttpService;
|
||||
import org.web3j.protocol.websocket.WebSocketService;
|
||||
import org.web3j.utils.Async;
|
||||
import org.web3j.utils.Convert;
|
||||
import org.web3j.utils.Convert.Unit;
|
||||
|
||||
public class PantheonNode implements AutoCloseable {
|
||||
public class PantheonNode implements Node, AutoCloseable {
|
||||
|
||||
private static final String LOCALHOST = "127.0.0.1";
|
||||
private static final Logger LOG = getLogger();
|
||||
private static final BigInteger MINIMUM_GAS_PRICE = BigInteger.valueOf(1000);
|
||||
private static final BigInteger TRANSFER_GAS_COST = BigInteger.valueOf(21000);
|
||||
|
||||
private final String name;
|
||||
private final Path homeDirectory;
|
||||
@@ -161,25 +154,7 @@ public class PantheonNode implements AutoCloseable {
|
||||
return web3j;
|
||||
}
|
||||
|
||||
public Hash transferFunds(
|
||||
final Account from, final Account to, final String amount, final Unit unit) {
|
||||
final RawTransaction transaction =
|
||||
RawTransaction.createEtherTransaction(
|
||||
from.getNextNonce(),
|
||||
MINIMUM_GAS_PRICE,
|
||||
TRANSFER_GAS_COST,
|
||||
to.getAddress(),
|
||||
Convert.toWei(amount, unit).toBigIntegerExact());
|
||||
final String signedTransactionData =
|
||||
toHexString(TransactionEncoder.signMessage(transaction, from.web3jCredentials()));
|
||||
try {
|
||||
return Hash.fromHexString(
|
||||
web3j().ethSendRawTransaction(signedTransactionData).send().getTransactionHash());
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getAccountBalance(final Account account) {
|
||||
try {
|
||||
final EthGetBalance balanceResponse =
|
||||
@@ -310,7 +285,7 @@ public class PantheonNode implements AutoCloseable {
|
||||
this.bootnodes = bootnodes;
|
||||
}
|
||||
|
||||
public MiningParameters getMiningParameters() {
|
||||
MiningParameters getMiningParameters() {
|
||||
return miningParameters;
|
||||
}
|
||||
|
||||
@@ -324,7 +299,7 @@ public class PantheonNode implements AutoCloseable {
|
||||
.toString();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
void stop() {
|
||||
if (web3j != null) {
|
||||
web3j.shutdown();
|
||||
web3j = null;
|
||||
@@ -359,4 +334,9 @@ public class PantheonNode implements AutoCloseable {
|
||||
|
||||
return eth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(final Transaction<T> transaction) {
|
||||
return transaction.execute(web3j());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2018 ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction;
|
||||
|
||||
import org.web3j.protocol.Web3j;
|
||||
|
||||
public interface Transaction<T> {
|
||||
|
||||
T execute(final Web3j node);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2018 ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction;
|
||||
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Accounts;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.web3j.utils.Convert.Unit;
|
||||
|
||||
public class Transactions {
|
||||
|
||||
private final Accounts accounts;
|
||||
|
||||
public Transactions(final Accounts accounts) {
|
||||
this.accounts = accounts;
|
||||
}
|
||||
|
||||
public TransferTransaction createTransfer(final Account recipient, final int amount) {
|
||||
return createTransfer(accounts.getPrimaryBenefactor(), recipient, amount);
|
||||
}
|
||||
|
||||
public TransferTransaction createTransfer(
|
||||
final Account sender, final Account recipient, final int amount) {
|
||||
return new TransferTransaction(sender, recipient, String.valueOf(amount), Unit.ETHER);
|
||||
}
|
||||
|
||||
public TransferTransactionSet createIncrementalTransfers(
|
||||
final Account sender, final Account recipient, final int etherAmount) {
|
||||
final List<TransferTransaction> transfers = new ArrayList<>();
|
||||
|
||||
for (int i = 1; i <= etherAmount; i++) {
|
||||
transfers.add(new TransferTransaction(sender, recipient, "1", Unit.ETHER));
|
||||
}
|
||||
|
||||
return new TransferTransactionSet(transfers);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2018 ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction;
|
||||
|
||||
import static org.web3j.utils.Numeric.toHexString;
|
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Hash;
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.web3j.crypto.RawTransaction;
|
||||
import org.web3j.crypto.TransactionEncoder;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.utils.Convert;
|
||||
import org.web3j.utils.Convert.Unit;
|
||||
|
||||
public class TransferTransaction implements Transaction<Hash> {
|
||||
|
||||
private static final BigInteger MINIMUM_GAS_PRICE = BigInteger.valueOf(1000);
|
||||
private static final BigInteger TRANSFER_GAS_COST = BigInteger.valueOf(21000);
|
||||
|
||||
private final Account sender;
|
||||
private final Account recipient;
|
||||
private final String amount;
|
||||
private final Unit unit;
|
||||
|
||||
public TransferTransaction(
|
||||
final Account sender, final Account recipient, final String amount, final Unit unit) {
|
||||
this.sender = sender;
|
||||
this.recipient = recipient;
|
||||
this.amount = amount;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash execute(final Web3j node) {
|
||||
final RawTransaction transaction =
|
||||
RawTransaction.createEtherTransaction(
|
||||
sender.getNextNonce(),
|
||||
MINIMUM_GAS_PRICE,
|
||||
TRANSFER_GAS_COST,
|
||||
recipient.getAddress(),
|
||||
Convert.toWei(amount, unit).toBigIntegerExact());
|
||||
final String signedTransactionData =
|
||||
toHexString(TransactionEncoder.signMessage(transaction, sender.web3jCredentials()));
|
||||
try {
|
||||
return Hash.fromHexString(
|
||||
node.ethSendRawTransaction(signedTransactionData).send().getTransactionHash());
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2018 ConsenSys AG.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction;
|
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Hash;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.web3j.protocol.Web3j;
|
||||
|
||||
public class TransferTransactionSet implements Transaction<List<Hash>> {
|
||||
|
||||
private final List<TransferTransaction> transactions;
|
||||
|
||||
public TransferTransactionSet(final List<TransferTransaction> transactions) {
|
||||
this.transactions = transactions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Hash> execute(final Web3j node) {
|
||||
final List<Hash> hashes = new ArrayList<>();
|
||||
|
||||
for (final TransferTransaction transaction : transactions) {
|
||||
hashes.add(transaction.execute(node));
|
||||
}
|
||||
|
||||
return hashes;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
*/
|
||||
package tech.pegasys.pantheon.tests.acceptance.mining;
|
||||
|
||||
import static org.web3j.utils.Convert.Unit.ETHER;
|
||||
import static tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNodeConfig.pantheonMinerNode;
|
||||
|
||||
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
|
||||
@@ -36,23 +35,24 @@ public class MiningAcceptanceTest extends AcceptanceTestBase {
|
||||
|
||||
@Test
|
||||
public void shouldMineTransactions() {
|
||||
final Account fromAccount = accounts.createAccount("account1", "50", ETHER, minerNode);
|
||||
final Account toAccount = accounts.createAccount("account2", "0", ETHER, minerNode);
|
||||
accounts.waitForAccountBalance(fromAccount, 50, minerNode);
|
||||
final Account sender = accounts.createAccount("account1");
|
||||
final Account receiver = accounts.createAccount("account2");
|
||||
minerNode.execute(transactions.createTransfer(sender, 50));
|
||||
cluster.verify(sender.balanceEquals(50));
|
||||
|
||||
accounts.incrementalTransfer(fromAccount, toAccount, 1, minerNode);
|
||||
accounts.waitForAccountBalance(toAccount, 1, minerNode);
|
||||
minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 1));
|
||||
cluster.verify(receiver.balanceEquals(1));
|
||||
|
||||
accounts.incrementalTransfer(fromAccount, toAccount, 2, minerNode);
|
||||
accounts.waitForAccountBalance(toAccount, 3, minerNode);
|
||||
minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 2));
|
||||
cluster.verify(receiver.balanceEquals(3));
|
||||
|
||||
accounts.incrementalTransfer(fromAccount, toAccount, 3, minerNode);
|
||||
accounts.waitForAccountBalance(toAccount, 6, minerNode);
|
||||
minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 3));
|
||||
cluster.verify(receiver.balanceEquals(6));
|
||||
|
||||
accounts.incrementalTransfer(fromAccount, toAccount, 4, minerNode);
|
||||
accounts.waitForAccountBalance(toAccount, 10, minerNode);
|
||||
minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 4));
|
||||
cluster.verify(receiver.balanceEquals(10));
|
||||
|
||||
accounts.incrementalTransfer(fromAccount, toAccount, 5, minerNode);
|
||||
accounts.waitForAccountBalance(toAccount, 15, minerNode);
|
||||
minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 5));
|
||||
cluster.verify(receiver.balanceEquals(15));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
// Create the light fork
|
||||
final Subscription lightForkSubscription = minerWebSocket.subscribe();
|
||||
|
||||
final Hash lightForkEvent = accounts.transfer(accountOne, 5, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 5);
|
||||
final Hash lightForkEvent = minerNode.execute(transactions.createTransfer(accountOne, 5));
|
||||
cluster.verify(accountOne.balanceEquals(5));
|
||||
|
||||
minerWebSocket.verifyTotalEventsReceived(1);
|
||||
lightForkSubscription.verifyEventReceived(lightForkEvent);
|
||||
@@ -86,14 +86,14 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
final Account heavyForkBenefactor = accounts.getSecondaryBenefactor();
|
||||
|
||||
final Hash heavyForkEventOne =
|
||||
accounts.transfer(heavyForkBenefactor, accountTwo, 1, minerNodeTwo);
|
||||
cluster.awaitPropagation(accountTwo, 1);
|
||||
minerNodeTwo.execute(transactions.createTransfer(heavyForkBenefactor, accountTwo, 1));
|
||||
cluster.verify(accountTwo.balanceEquals(1));
|
||||
final Hash heavyForkEventTwo =
|
||||
accounts.transfer(heavyForkBenefactor, accountTwo, 2, minerNodeTwo);
|
||||
cluster.awaitPropagation(accountTwo, 1 + 2);
|
||||
minerNodeTwo.execute(transactions.createTransfer(heavyForkBenefactor, accountTwo, 2));
|
||||
cluster.verify(accountTwo.balanceEquals(1 + 2));
|
||||
final Hash heavyForkEventThree =
|
||||
accounts.transfer(heavyForkBenefactor, accountTwo, 3, minerNodeTwo);
|
||||
cluster.awaitPropagation(accountTwo, 1 + 2 + 3);
|
||||
minerNodeTwo.execute(transactions.createTransfer(heavyForkBenefactor, accountTwo, 3));
|
||||
cluster.verify(accountTwo.balanceEquals(1 + 2 + 3));
|
||||
|
||||
heavyForkWebSocket.verifyTotalEventsReceived(3);
|
||||
heavyForkSubscription.verifyEventReceived(heavyForkEventOne);
|
||||
@@ -121,8 +121,9 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
|
||||
// This publish give time needed for heavy fork to be chosen
|
||||
final Hash mergedForksEventOne =
|
||||
accounts.transfer(accounts.getSecondaryBenefactor(), accountTwo, 3, minerNodeTwo);
|
||||
cluster.awaitPropagation(accountTwo, 9);
|
||||
minerNodeTwo.execute(
|
||||
transactions.createTransfer(accounts.getSecondaryBenefactor(), accountTwo, 3));
|
||||
cluster.verify(accountTwo.balanceEquals(9));
|
||||
|
||||
minerMergedForksWebSocket.verifyTotalEventsReceived(1);
|
||||
minerMergedForksSubscription.verifyEventReceived(lightForkEvent);
|
||||
@@ -134,13 +135,14 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
|
||||
// Check that account two (funded in heavier chain) can be mined on miner one (from lighter
|
||||
// chain)
|
||||
final Hash mergedForksEventTwo = accounts.transfer(accountTwo, 3, minerNode);
|
||||
cluster.awaitPropagation(accountTwo, 9 + 3);
|
||||
final Hash mergedForksEventTwo = minerNode.execute(transactions.createTransfer(accountTwo, 3));
|
||||
cluster.verify(accountTwo.balanceEquals(9 + 3));
|
||||
|
||||
// Check that account one (funded in lighter chain) can be mined on miner two (from heavier
|
||||
// chain)
|
||||
final Hash mergedForksEventThree = accounts.transfer(accountOne, 2, minerNodeTwo);
|
||||
cluster.awaitPropagation(accountOne, 5 + 2);
|
||||
final Hash mergedForksEventThree =
|
||||
minerNodeTwo.execute(transactions.createTransfer(accountOne, 2));
|
||||
cluster.verify(accountOne.balanceEquals(5 + 2));
|
||||
|
||||
minerMergedForksWebSocket.verifyTotalEventsReceived(1 + 1 + 1);
|
||||
minerMergedForksSubscription.verifyEventReceived(mergedForksEventTwo);
|
||||
@@ -157,8 +159,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
public void subscriptionToMinerNodeMustReceivePublishEvent() {
|
||||
final Subscription minerSubscription = minerWebSocket.subscribe();
|
||||
|
||||
final Hash event = accounts.transfer(accountOne, 4, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 4);
|
||||
final Hash event = minerNode.execute(transactions.createTransfer(accountOne, 4));
|
||||
cluster.verify(accountOne.balanceEquals(4));
|
||||
|
||||
minerWebSocket.verifyTotalEventsReceived(1);
|
||||
minerSubscription.verifyEventReceived(event);
|
||||
@@ -170,8 +172,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
public void subscriptionToArchiveNodeMustReceivePublishEvent() {
|
||||
final Subscription archiveSubscription = archiveWebSocket.subscribe();
|
||||
|
||||
final Hash event = accounts.transfer(accountOne, 23, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 23);
|
||||
final Hash event = minerNode.execute(transactions.createTransfer(accountOne, 23));
|
||||
cluster.verify(accountOne.balanceEquals(23));
|
||||
|
||||
archiveWebSocket.verifyTotalEventsReceived(1);
|
||||
archiveSubscription.verifyEventReceived(event);
|
||||
@@ -187,8 +189,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
final Subscription archiveSubscriptionTwo = archiveWebSocket.subscribe();
|
||||
final Subscription archiveSubscriptionThree = archiveWebSocket.subscribe();
|
||||
|
||||
final Hash event = accounts.transfer(accountOne, 30, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 30);
|
||||
final Hash event = minerNode.execute(transactions.createTransfer(accountOne, 30));
|
||||
cluster.verify(accountOne.balanceEquals(30));
|
||||
|
||||
minerWebSocket.verifyTotalEventsReceived(2);
|
||||
minerSubscriptionOne.verifyEventReceived(event);
|
||||
@@ -210,15 +212,15 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
public void subscriptionToMinerNodeMustReceiveEveryPublishEvent() {
|
||||
final Subscription minerSubscription = minerWebSocket.subscribe();
|
||||
|
||||
final Hash eventOne = accounts.transfer(accountOne, 1, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 1);
|
||||
final Hash eventOne = minerNode.execute(transactions.createTransfer(accountOne, 1));
|
||||
cluster.verify(accountOne.balanceEquals(1));
|
||||
|
||||
minerWebSocket.verifyTotalEventsReceived(1);
|
||||
minerSubscription.verifyEventReceived(eventOne);
|
||||
|
||||
final Hash eventTwo = accounts.transfer(accountOne, 4, minerNode);
|
||||
final Hash eventThree = accounts.transfer(accountOne, 5, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 1 + 4 + 5);
|
||||
final Hash eventTwo = minerNode.execute(transactions.createTransfer(accountOne, 4));
|
||||
final Hash eventThree = minerNode.execute(transactions.createTransfer(accountOne, 5));
|
||||
cluster.verify(accountOne.balanceEquals(1 + 4 + 5));
|
||||
|
||||
minerWebSocket.verifyTotalEventsReceived(3);
|
||||
minerSubscription.verifyEventReceived(eventTwo);
|
||||
@@ -231,16 +233,16 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
public void subscriptionToArchiveNodeMustReceiveEveryPublishEvent() {
|
||||
final Subscription archiveSubscription = archiveWebSocket.subscribe();
|
||||
|
||||
final Hash eventOne = accounts.transfer(accountOne, 2, minerNode);
|
||||
final Hash eventTwo = accounts.transfer(accountOne, 5, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 2 + 5);
|
||||
final Hash eventOne = minerNode.execute(transactions.createTransfer(accountOne, 2));
|
||||
final Hash eventTwo = minerNode.execute(transactions.createTransfer(accountOne, 5));
|
||||
cluster.verify(accountOne.balanceEquals(2 + 5));
|
||||
|
||||
archiveWebSocket.verifyTotalEventsReceived(2);
|
||||
archiveSubscription.verifyEventReceived(eventOne);
|
||||
archiveSubscription.verifyEventReceived(eventTwo);
|
||||
|
||||
final Hash eventThree = accounts.transfer(accountOne, 8, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 2 + 5 + 8);
|
||||
final Hash eventThree = minerNode.execute(transactions.createTransfer(accountOne, 8));
|
||||
cluster.verify(accountOne.balanceEquals(2 + 5 + 8));
|
||||
|
||||
archiveWebSocket.verifyTotalEventsReceived(3);
|
||||
archiveSubscription.verifyEventReceived(eventThree);
|
||||
@@ -256,9 +258,9 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase {
|
||||
final Subscription archiveSubscriptionTwo = archiveWebSocket.subscribe();
|
||||
final Subscription archiveSubscriptionThree = archiveWebSocket.subscribe();
|
||||
|
||||
final Hash eventOne = accounts.transfer(accountOne, 10, minerNode);
|
||||
final Hash eventTwo = accounts.transfer(accountOne, 5, minerNode);
|
||||
cluster.awaitPropagation(accountOne, 10 + 5);
|
||||
final Hash eventOne = minerNode.execute(transactions.createTransfer(accountOne, 10));
|
||||
final Hash eventTwo = minerNode.execute(transactions.createTransfer(accountOne, 5));
|
||||
cluster.verify(accountOne.balanceEquals(10 + 5));
|
||||
|
||||
minerWebSocket.verifyTotalEventsReceived(4);
|
||||
minerSubscriptionOne.verifyEventReceived(eventOne);
|
||||
|
||||
Reference in New Issue
Block a user