Refactor Reference Tests (#1310)

Move key referenceTest classes relating to reading the JSON data into a
"main" java package so that it can be included in other production
classes.  Some classes were renamed to make their intent clearer. Other
smaller changes that bring classes in line with current coding
standards were done.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
pull/1314/head
Danno Ferrin 4 years ago committed by GitHub
parent 313d6a3965
commit 0bf8a06686
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      ethereum/blockcreation/build.gradle
  2. 4
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/BlockTransactionSelectorTest.java
  3. 1
      ethereum/core/build.gradle
  4. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/TransactionTest.java
  5. 12
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java
  6. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTestTools.java
  7. 3
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracerTest.java
  8. 22
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java
  9. 6
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/VMReferenceTest.java
  10. 6
      ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/vm/BlockchainReferenceTest.java.template
  11. 6
      ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTest.java.template
  12. 1
      ethereum/eth/build.gradle
  13. 8
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetHeadersFromPeerByHashTaskTest.java
  14. 8
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetHeadersFromPeerByNumberTaskTest.java
  15. 13
      ethereum/referencetests/build.gradle
  16. 24
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java
  17. 89
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/EnvironmentInformation.java
  18. 47
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/GeneralStateTestCaseEipSpec.java
  19. 22
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/GeneralStateTestCaseSpec.java
  20. 11
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestBlockchain.java
  21. 9
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestCode.java
  22. 33
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java
  23. 12
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java
  24. 17
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java
  25. 20
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/StateTestVersionedTransaction.java
  26. 20
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/VMReferenceTestCaseSpec.java

@ -28,6 +28,7 @@ dependencies {
testImplementation project(path: ':config', configuration: 'testSupportArtifacts')
testImplementation project(path: ':ethereum:core', configuration: 'testArtifacts')
testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
testImplementation project(':ethereum:referencetests')
testImplementation project(':metrics:core')
testImplementation project(':testutil')

@ -47,7 +47,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidator;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.vm.TestBlockchain;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.testutil.TestClock;
@ -68,7 +68,7 @@ public class BlockTransactionSelectorTest {
private static final KeyPair keyPair = KeyPair.generate();
private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private final Blockchain blockchain = new TestBlockchain();
private final Blockchain blockchain = new ReferenceTestBlockchain();
private final PendingTransactions pendingTransactions =
new PendingTransactions(
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS,

@ -52,6 +52,7 @@ dependencies {
runtimeOnly 'org.apache.logging.log4j:log4j-core'
testImplementation project(path: ':config', configuration: 'testSupportArtifacts')
testImplementation project(path:':ethereum:referencetests')
testImplementation project(path:':ethereum:referencetests', configuration: 'testOutput')
testImplementation project(':testutil')

@ -18,8 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeTrue;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidator;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.vm.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.testutil.JsonTestParameters;
import java.util.Collection;

@ -26,8 +26,8 @@ import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.fees.TransactionGasBudgetCalculator;
import org.hyperledger.besu.ethereum.vm.TestBlockchain;
import org.hyperledger.besu.ethereum.vm.WorldStateMock;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState;
import org.junit.Test;
@ -39,7 +39,7 @@ public class MainnetBlockProcessorTest {
@Test
public void noAccountCreatedWhenBlockRewardIsZeroAndSkipped() {
final Blockchain blockchain = new TestBlockchain();
final Blockchain blockchain = new ReferenceTestBlockchain();
final MainnetBlockProcessor blockProcessor =
new MainnetBlockProcessor(
transactionProcessor,
@ -49,7 +49,7 @@ public class MainnetBlockProcessorTest {
true,
TransactionGasBudgetCalculator.frontier());
final MutableWorldState worldState = WorldStateMock.create(emptyMap());
final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap());
final Hash initialHash = worldState.rootHash();
final BlockHeader emptyBlockHeader =
@ -65,7 +65,7 @@ public class MainnetBlockProcessorTest {
@Test
public void accountCreatedWhenBlockRewardIsZeroAndNotSkipped() {
final Blockchain blockchain = new TestBlockchain();
final Blockchain blockchain = new ReferenceTestBlockchain();
final MainnetBlockProcessor blockProcessor =
new MainnetBlockProcessor(
transactionProcessor,
@ -75,7 +75,7 @@ public class MainnetBlockProcessorTest {
false,
TransactionGasBudgetCalculator.frontier());
final MutableWorldState worldState = WorldStateMock.create(emptyMap());
final MutableWorldState worldState = ReferenceTestWorldState.create(emptyMap());
final Hash initialHash = worldState.rootHash();
final BlockHeader emptyBlockHeader =

@ -26,6 +26,8 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.referencetests.BlockchainReferenceTestCaseSpec;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.testutil.JsonTestParameters;

@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
import org.hyperledger.besu.ethereum.vm.Operation.OperationResult;
import java.util.Map;
@ -192,7 +193,7 @@ public class DebugOperationTracerTest {
private MessageFrameTestFixture validMessageFrameBuilder() {
final BlockHeader blockHeader = new BlockHeaderTestFixture().number(1).buildHeader();
final TestBlockchain blockchain = new TestBlockchain(blockHeader.getNumber());
final ReferenceTestBlockchain blockchain = new ReferenceTestBlockchain(blockHeader.getNumber());
return new MessageFrameTestFixture()
.initialGas(INITIAL_GAS)
.worldState(worldUpdater)

@ -27,6 +27,10 @@ import org.hyperledger.besu.ethereum.core.WorldState;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseEipSpec;
import org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseSpec;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestProtocolSchedules;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState;
import org.hyperledger.besu.testutil.JsonTestParameters;
@ -108,9 +112,9 @@ public class GeneralStateReferenceTestTools {
}
public static void executeTest(final GeneralStateTestCaseEipSpec spec) {
final BlockHeader blockHeader = spec.blockHeader();
final WorldState initialWorldState = spec.initialWorldState();
final Transaction transaction = spec.transaction();
final BlockHeader blockHeader = spec.getBlockHeader();
final WorldState initialWorldState = spec.getInitialWorldState();
final Transaction transaction = spec.getTransaction();
final MutableWorldState worldState = new DefaultMutableWorldState(initialWorldState);
// Several of the GeneralStateTests check if the transaction could potentially
@ -121,9 +125,9 @@ public class GeneralStateReferenceTestTools {
return;
}
final TransactionProcessor processor = transactionProcessor(spec.eip());
final TransactionProcessor processor = transactionProcessor(spec.getFork());
final WorldUpdater worldStateUpdater = worldState.updater();
final TestBlockchain blockchain = new TestBlockchain(blockHeader.getNumber());
final ReferenceTestBlockchain blockchain = new ReferenceTestBlockchain(blockHeader.getNumber());
final TransactionProcessor.Result result =
processor.processTransaction(
blockchain,
@ -134,20 +138,20 @@ public class GeneralStateReferenceTestTools {
new BlockHashLookup(blockHeader, blockchain),
false,
TransactionValidationParams.processingBlock());
final Account coinbase = worldStateUpdater.getOrCreate(spec.blockHeader().getCoinbase());
if (coinbase != null && coinbase.isEmpty() && shouldClearEmptyAccounts(spec.eip())) {
final Account coinbase = worldStateUpdater.getOrCreate(spec.getBlockHeader().getCoinbase());
if (coinbase != null && coinbase.isEmpty() && shouldClearEmptyAccounts(spec.getFork())) {
worldStateUpdater.deleteAccount(coinbase.getAddress());
}
worldStateUpdater.commit();
// Check the world state root hash.
final Hash expectedRootHash = spec.expectedRootHash();
final Hash expectedRootHash = spec.getExpectedRootHash();
assertThat(worldState.rootHash())
.withFailMessage("Unexpected world state root hash; computed state: %s", worldState)
.isEqualTo(expectedRootHash);
// Check the logs.
final Hash expectedLogsHash = spec.expectedLogsHash();
final Hash expectedLogsHash = spec.getExpectedLogsHash();
final List<Log> logs = result.getLogs();
assertThat(Hash.hash(RLP.encode(out -> out.writeList(logs, Log::writeTo))))
.withFailMessage("Unmatched logs hash. Generated logs: %s", logs)

@ -24,6 +24,9 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSpecs;
import org.hyperledger.besu.ethereum.mainnet.MutableProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionValidator;
import org.hyperledger.besu.ethereum.referencetests.EnvironmentInformation;
import org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain;
import org.hyperledger.besu.ethereum.referencetests.VMReferenceTestCaseSpec;
import org.hyperledger.besu.ethereum.vm.operations.ReturnStack;
import org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState;
import org.hyperledger.besu.testutil.JsonTestParameters;
@ -101,7 +104,8 @@ public class VMReferenceTest extends AbstractRetryingTest {
final ReturnStack returnStack = new ReturnStack();
final TestBlockchain blockchain = new TestBlockchain(execEnv.getBlockHeader().getNumber());
final ReferenceTestBlockchain blockchain =
new ReferenceTestBlockchain(execEnv.getBlockHeader().getNumber());
final MessageFrame frame =
MessageFrame.builder()
.type(MessageFrame.Type.MESSAGE_CALL)

@ -3,7 +3,7 @@ package org.hyperledger.besu.ethereum.vm.blockchain;
import static org.hyperledger.besu.ethereum.vm.BlockchainReferenceTestTools.executeTest;
import static org.hyperledger.besu.ethereum.vm.BlockchainReferenceTestTools.generateTestParametersForConfig;
import org.hyperledger.besu.ethereum.vm.BlockchainReferenceTestCaseSpec;
import org.hyperledger.besu.ethereum.referencetests.BlockchainReferenceTestCaseSpec;
import java.util.Collection;
@ -25,16 +25,14 @@ public class %%TESTS_NAME%% {
return generateTestParametersForConfig(TEST_CONFIG_FILE_DIR_PATH);
}
private final String name;
private final BlockchainReferenceTestCaseSpec spec;
public %%TESTS_NAME%%(
final String name,
final BlockchainReferenceTestCaseSpec spec,
final boolean runTest) {
this.name = name;
this.spec = spec;
assumeTrue("Test was blacklisted", runTest);
assumeTrue("Test " + name + " was ignored", runTest);
}
@Test

@ -3,7 +3,7 @@ package org.hyperledger.besu.ethereum.vm.generalstate;
import static org.hyperledger.besu.ethereum.vm.GeneralStateReferenceTestTools.executeTest;
import static org.hyperledger.besu.ethereum.vm.GeneralStateReferenceTestTools.generateTestParametersForConfig;
import org.hyperledger.besu.ethereum.vm.GeneralStateTestCaseEipSpec;
import org.hyperledger.besu.ethereum.referencetests.GeneralStateTestCaseEipSpec;
import java.util.Collection;
@ -25,16 +25,14 @@ public class %%TESTS_NAME%% {
return generateTestParametersForConfig(TEST_CONFIG_FILE_DIR_PATH);
}
private final String name;
private final GeneralStateTestCaseEipSpec spec;
public %%TESTS_NAME%%(
final String name,
final GeneralStateTestCaseEipSpec spec,
final boolean runTest) {
this.name = name;
this.spec = spec;
assumeTrue("Test was blacklisted", runTest);
assumeTrue("Test " + name + " was ignored", runTest);
}
@Test

@ -52,6 +52,7 @@ dependencies {
testImplementation project(path: ':ethereum:core', configuration: 'testArtifacts')
testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
testImplementation project(':ethereum:mock-p2p')
testImplementation project(':ethereum:referencetests')
testImplementation project(path: ':metrics:core', configuration: 'testSupportArtifacts')
testImplementation project(':testutil')

@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.eth.manager.task;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hyperledger.besu.ethereum.vm.TestBlockchain.generateTestBlockHash;
import static org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain.generateTestBlockHash;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ -163,11 +163,11 @@ public class GetHeadersFromPeerByHashTaskTest extends PeerMessageTaskTest<List<B
0,
false,
metricsSystem);
Optional<List<BlockHeader>> optionalBlockHeaders =
final Optional<List<BlockHeader>> optionalBlockHeaders =
task.processResponse(false, BlockHeadersMessage.create(headers), peerMock);
assertThat(optionalBlockHeaders).isNotNull();
assertThat(optionalBlockHeaders).isPresent();
List<BlockHeader> blockHeaders = optionalBlockHeaders.get();
final List<BlockHeader> blockHeaders = optionalBlockHeaders.get();
MatcherAssert.assertThat(blockHeaders, hasSize(2));
verify(peerMock, times(0)).disconnect(any());
}
@ -191,7 +191,7 @@ public class GetHeadersFromPeerByHashTaskTest extends PeerMessageTaskTest<List<B
0,
false,
metricsSystem);
Optional<List<BlockHeader>> optionalBlockHeaders =
final Optional<List<BlockHeader>> optionalBlockHeaders =
task.processResponse(false, BlockHeadersMessage.create(headers), peerMock);
assertThat(optionalBlockHeaders).isNotNull();
assertThat(optionalBlockHeaders).isEmpty();

@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.eth.manager.task;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hyperledger.besu.ethereum.vm.TestBlockchain.generateTestBlockHash;
import static org.hyperledger.besu.ethereum.referencetests.ReferenceTestBlockchain.generateTestBlockHash;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ -141,11 +141,11 @@ public class GetHeadersFromPeerByNumberTaskTest extends PeerMessageTaskTest<List
final AbstractGetHeadersFromPeerTask task =
new GetHeadersFromPeerByNumberTask(
protocolSchedule, ethContext, block1.getNumber(), 2, 0, false, metricsSystem);
Optional<List<BlockHeader>> optionalBlockHeaders =
final Optional<List<BlockHeader>> optionalBlockHeaders =
task.processResponse(false, BlockHeadersMessage.create(headers), peerMock);
assertThat(optionalBlockHeaders).isNotNull();
assertThat(optionalBlockHeaders).isPresent();
List<BlockHeader> blockHeaders = optionalBlockHeaders.get();
final List<BlockHeader> blockHeaders = optionalBlockHeaders.get();
MatcherAssert.assertThat(blockHeaders, hasSize(2));
verify(peerMock, times(0)).disconnect(any());
}
@ -161,7 +161,7 @@ public class GetHeadersFromPeerByNumberTaskTest extends PeerMessageTaskTest<List
final AbstractGetHeadersFromPeerTask task =
new GetHeadersFromPeerByNumberTask(
protocolSchedule, ethContext, block1.getNumber(), 2, 0, false, metricsSystem);
Optional<List<BlockHeader>> optionalBlockHeaders =
final Optional<List<BlockHeader>> optionalBlockHeaders =
task.processResponse(false, BlockHeadersMessage.create(headers), peerMock);
assertThat(optionalBlockHeaders).isNotNull();
assertThat(optionalBlockHeaders).isEmpty();

@ -23,7 +23,18 @@ sourceSets {
configurations { testOutput }
dependencies { testOutput sourceSets.test.output }
dependencies {
implementation project(':config')
implementation project(':crypto')
implementation project(':ethereum:core')
implementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
implementation project(':ethereum:rlp')
implementation project(':services:kvstore')
implementation 'com.fasterxml.jackson.core:jackson-databind'
testOutput sourceSets.test.output
}
task ('validateReferenceTestSubmodule') {
description = "Checks that the reference tests submodule is not accidentially changed"

@ -11,10 +11,9 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
import static org.hyperledger.besu.ethereum.vm.WorldStateMock.insertAccount;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
@ -50,7 +49,7 @@ public class BlockchainReferenceTestCaseSpec {
private final CandidateBlock[] candidateBlocks;
private final BlockHeaderMock genesisBlockHeader;
private final ReferenceTestBlockHeader genesisBlockHeader;
private final Hash lastBlockHash;
@ -62,15 +61,16 @@ public class BlockchainReferenceTestCaseSpec {
private final ProtocolContext protocolContext;
private static WorldStateArchive buildWorldStateArchive(
final Map<String, WorldStateMock.AccountMock> accounts) {
final Map<String, ReferenceTestWorldState.AccountMock> accounts) {
final WorldStateArchive worldStateArchive =
InMemoryStorageProvider.createInMemoryWorldStateArchive();
final MutableWorldState worldState = worldStateArchive.getMutable();
final WorldUpdater updater = worldState.updater();
for (final Map.Entry<String, WorldStateMock.AccountMock> entry : accounts.entrySet()) {
insertAccount(updater, Address.fromHexString(entry.getKey()), entry.getValue());
for (final Map.Entry<String, ReferenceTestWorldState.AccountMock> entry : accounts.entrySet()) {
ReferenceTestWorldState.insertAccount(
updater, Address.fromHexString(entry.getKey()), entry.getValue());
}
updater.commit();
@ -88,9 +88,9 @@ public class BlockchainReferenceTestCaseSpec {
public BlockchainReferenceTestCaseSpec(
@JsonProperty("network") final String network,
@JsonProperty("blocks") final CandidateBlock[] candidateBlocks,
@JsonProperty("genesisBlockHeader") final BlockHeaderMock genesisBlockHeader,
@JsonProperty("genesisBlockHeader") final ReferenceTestBlockHeader genesisBlockHeader,
@SuppressWarnings("unused") @JsonProperty("genesisRLP") final String genesisRLP,
@JsonProperty("pre") final Map<String, WorldStateMock.AccountMock> accounts,
@JsonProperty("pre") final Map<String, ReferenceTestWorldState.AccountMock> accounts,
@JsonProperty("lastblockhash") final String lastBlockHash,
@JsonProperty("sealEngine") final String sealEngine) {
this.network = network;
@ -135,10 +135,10 @@ public class BlockchainReferenceTestCaseSpec {
return sealEngine;
}
public static class BlockHeaderMock extends BlockHeader {
public static class ReferenceTestBlockHeader extends BlockHeader {
@JsonCreator
public BlockHeaderMock(
public ReferenceTestBlockHeader(
@JsonProperty("parentHash") final String parentHash,
@JsonProperty("uncleHash") final String uncleHash,
@JsonProperty("coinbase") final String coinbase,
@ -214,7 +214,7 @@ public class BlockchainReferenceTestCaseSpec {
@JsonProperty("blockHeader") final Object blockHeader,
@JsonProperty("transactions") final Object transactions,
@JsonProperty("uncleHeaders") final Object uncleHeaders) {
Boolean valid = true;
boolean valid = true;
// The BLOCK__WrongCharAtRLP_0 test has an invalid character in its rlp string.
Bytes rlpAttempt = null;
try {

@ -11,14 +11,16 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.ethereum.core.Account;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.vm.Code;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@ -61,21 +63,25 @@ public class EnvironmentInformation {
/**
* Public constructor.
*
* @param code The code to be executed.
* @param account The address of the currently executing account.
* @param balance Balance of the account being executed
* @param caller The caller address.
* @param origin The sender address of the original transaction.
* @param code The code to be executed.
* @param data The data of the current environment that pertains to the input data passed with the
* message call instruction or transaction.
* @param value The deposited value by the instruction/transaction responsible for this execution.
* @param gas The amount of gas allocated to the transaction
* @param gasPrice The gas price specified by the originating transaction.
* @param origin The sender address of the original transaction. message call instruction or
* transaction.
* @param value The deposited value by the instruction/transaction responsible for this execution.
* @param version the account version of the account
*/
@SuppressWarnings("unused") // jackson reflected constructor
@JsonCreator
public EnvironmentInformation(
@JsonProperty("address") final String account,
@JsonProperty("balance") final String balance,
@JsonProperty("caller") final String caller,
@JsonProperty("code") final CodeMock code,
@JsonProperty("code") final ReferenceTestCode code,
@JsonProperty("data") final String data,
@JsonProperty("gas") final String gas,
@JsonProperty("gasPrice") final String gasPrice,
@ -130,61 +136,110 @@ public class EnvironmentInformation {
this.blockHeader = blockHeader;
}
/** @return The block header. */
/**
* Returns the block header.
*
* @return the block header
*/
public BlockHeader getBlockHeader() {
return blockHeader;
}
/** @return The address of the currently executing account. */
/**
* Returns the address of the currently executing account.
*
* @return the address of the currently executing account.
*/
public Address getAccountAddress() {
return accountAddress;
}
/** @return The balance of the currently executing account */
/**
* Returns the balance of the currently executing account
*
* @return the balance of the currently executing account
*/
public Wei getAccountBalance() {
return accountBalance;
}
/** @return Address of the caller. */
/**
* Returns address of the caller.
*
* @return address of the caller.
*/
public Address getCallerAddress() {
return callerAddress;
}
/** @return The call value. */
/**
* Returns the call value.
*
* @return the call value.
*/
public Wei getValue() {
return value;
}
/** @return Code to be executed. */
/**
* Returns code to be executed.
*
* @return code to be executed.
*/
public Code getCode() {
return code;
}
/** @return The input data to be used. */
/**
* Returns the input data to be used.
*
* @return the input data to be used.
*/
public Bytes getData() {
return data;
}
/** @return The call depth of the current message-call/contract creation. */
/**
* Returns the call depth of the current message-call/contract creation.
*
* @return the call depth of the current message-call/contract creation.
*/
public int getDepth() {
return depth;
}
/** @return The gas price specified by the originating transaction. */
/**
* Returns the gas price specified by the originating transaction.
*
* @return the gas price specified by the originating transaction.
*/
public Wei getGasPrice() {
return gasPrice;
}
/** @return The amount of gas available. */
/**
* Returns the amount of gas available.
*
* @return the amount of gas available.
*/
public Gas getGas() {
return gas;
}
/** @return The sender address of the original transaction. */
/**
* Returns the sender address of the original transaction.
*
* @return the sender address of the original transaction.
*/
public Address getOriginAddress() {
return originAddress;
}
/**
* Returns the account version.
*
* @return the account version.
*/
public int getVersion() {
return version;
}

@ -11,8 +11,9 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
@ -23,7 +24,7 @@ import java.util.function.Supplier;
public class GeneralStateTestCaseEipSpec {
private final String eip;
private final String fork;
// Creating the actual transaction is expensive because the json test file does not give us the
// transaction but rather the private key to sign, and so we have to do the signing. And we don't
@ -45,42 +46,64 @@ public class GeneralStateTestCaseEipSpec {
private final BlockHeader blockHeader;
private final int dataIndex;
private final int gasIndex;
private final int valueIndex;
GeneralStateTestCaseEipSpec(
final String eip,
final String fork,
final Supplier<Transaction> transactionSupplier,
final WorldState initialWorldState,
final Hash expectedRootHash,
final Hash expectedLogsHash,
final BlockHeader blockHeader) {
this.eip = eip;
final BlockHeader blockHeader,
final int dataIndex,
final int gasIndex,
final int valueIndex) {
this.fork = fork;
this.transactionSupplier = transactionSupplier;
this.initialWorldState = initialWorldState;
this.expectedRootHash = expectedRootHash;
this.expectedLogsHash = expectedLogsHash;
this.blockHeader = blockHeader;
this.dataIndex = dataIndex;
this.gasIndex = gasIndex;
this.valueIndex = valueIndex;
}
String eip() {
return eip;
public String getFork() {
return fork;
}
WorldState initialWorldState() {
public WorldState getInitialWorldState() {
return initialWorldState;
}
Hash expectedRootHash() {
public Hash getExpectedRootHash() {
return expectedRootHash;
}
Hash expectedLogsHash() {
public Hash getExpectedLogsHash() {
return expectedLogsHash;
}
Transaction transaction() {
public Transaction getTransaction() {
return transactionSupplier.get();
}
BlockHeader blockHeader() {
public BlockHeader getBlockHeader() {
return blockHeader;
}
public int getDataIndex() {
return dataIndex;
}
public int getGasIndex() {
return gasIndex;
}
public int getValueIndex() {
return valueIndex;
}
}

@ -11,11 +11,11 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderMock;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Transaction;
@ -38,8 +38,8 @@ public class GeneralStateTestCaseSpec {
@JsonCreator
public GeneralStateTestCaseSpec(
@JsonProperty("env") final BlockHeaderMock blockHeader,
@JsonProperty("pre") final WorldStateMock initialWorldState,
@JsonProperty("env") final ReferenceTestEnv blockHeader,
@JsonProperty("pre") final ReferenceTestWorldState initialWorldState,
@JsonProperty("post") final Map<String, List<PostSection>> postSection,
@JsonProperty("transaction") final StateTestVersionedTransaction versionedTransaction) {
this.finalStateSpecs =
@ -48,7 +48,7 @@ public class GeneralStateTestCaseSpec {
private Map<String, List<GeneralStateTestCaseEipSpec>> generate(
final BlockHeader blockHeader,
final WorldStateMock initialWorldState,
final ReferenceTestWorldState initialWorldState,
final Map<String, List<PostSection>> postSections,
final StateTestVersionedTransaction versionedTransaction) {
@ -62,14 +62,22 @@ public class GeneralStateTestCaseSpec {
final Supplier<Transaction> txSupplier = () -> versionedTransaction.get(p.indexes);
specs.add(
new GeneralStateTestCaseEipSpec(
eip, txSupplier, initialWorldState, p.rootHash, p.logsHash, blockHeader));
eip,
txSupplier,
initialWorldState,
p.rootHash,
p.logsHash,
blockHeader,
p.indexes.data,
p.indexes.gas,
p.indexes.value));
}
res.put(eip, specs);
}
return res;
}
Map<String, List<GeneralStateTestCaseEipSpec>> finalStateSpecs() {
public Map<String, List<GeneralStateTestCaseEipSpec>> finalStateSpecs() {
return finalStateSpecs;
}

@ -11,8 +11,9 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import static java.nio.charset.StandardCharsets.UTF_8;
@ -48,7 +49,7 @@ import org.apache.tuweni.bytes.Bytes;
* (GeneralStateTests) require a block's hash to be to be the hash of the string of it's block
* number.
*/
public class TestBlockchain implements Blockchain {
public class ReferenceTestBlockchain implements Blockchain {
// Maximum number of blocks prior to the chain head that can be retrieved by hash.
private static final long MAXIMUM_BLOCKS_BEHIND_HEAD = 256;
@ -58,11 +59,11 @@ public class TestBlockchain implements Blockchain {
"Chain head is inherently non-deterministic. The block currently being processed should be treated as the chain head.";
private final Map<Hash, BlockHeader> hashToHeader = new HashMap<>();
public TestBlockchain() {
public ReferenceTestBlockchain() {
this(0);
}
public TestBlockchain(final long chainHeadBlockNumber) {
public ReferenceTestBlockchain(final long chainHeadBlockNumber) {
for (long blockNumber = Math.max(0L, chainHeadBlockNumber - MAXIMUM_BLOCKS_BEHIND_HEAD);
blockNumber < chainHeadBlockNumber;
blockNumber++) {
@ -161,7 +162,7 @@ public class TestBlockchain implements Blockchain {
}
public static class NonDeterministicOperationException extends RuntimeException {
public NonDeterministicOperationException(final String message) {
NonDeterministicOperationException(final String message) {
super(message);
}
}

@ -11,14 +11,17 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.ethereum.vm.Code;
import com.fasterxml.jackson.annotation.JsonCreator;
import org.apache.tuweni.bytes.Bytes;
/** A mock for representing EVM Code associated with an account. */
public class CodeMock extends Code {
public class ReferenceTestCode extends Code {
/**
* Public constructor.
@ -26,7 +29,7 @@ public class CodeMock extends Code {
* @param bytes - A hex string representation of the code.
*/
@JsonCreator
public CodeMock(final String bytes) {
public ReferenceTestCode(final String bytes) {
super(Bytes.fromHexString(bytes));
}
}

@ -11,37 +11,47 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.core;
package org.hyperledger.besu.ethereum.referencetests;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.LogsBloomFilter;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.vm.TestBlockchain;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.tuweni.bytes.Bytes;
/** A memory mock for testing. */
/** A memory holder for testing. */
@JsonIgnoreProperties("previousHash")
public class BlockHeaderMock extends BlockHeader {
public class ReferenceTestEnv extends BlockHeader {
/**
* Public constructor.
*
* @param coinbase The beneficiary address.
* @param gasLimit The gas limit of the current block.
* @param number The number to execute.
* @param coinbase Coinbase/beneficiary for the mock block being tested.
* @param difficulty Difficulty for the mock block being tested.
* @param gasLimit Gas Limit for the mock block being tested.
* @param number Block number for the mock block being tested.
* @param timestamp Timestamp for the mock block being tested.
*/
@JsonCreator
public BlockHeaderMock(
public ReferenceTestEnv(
@JsonProperty("currentCoinbase") final String coinbase,
@JsonProperty("currentDifficulty") final String difficulty,
@JsonProperty("currentGasLimit") final String gasLimit,
@JsonProperty("currentNumber") final String number,
@JsonProperty("currentTimestamp") final String timestamp) {
super(
TestBlockchain.generateTestBlockHash(Long.decode(number) - 1),
generateTestBlockHash(Long.decode(number) - 1),
Hash.EMPTY, // ommersHash
Address.fromHexString(coinbase),
Hash.EMPTY, // stateRoot
@ -59,4 +69,9 @@ public class BlockHeaderMock extends BlockHeader {
0L,
new MainnetBlockHeaderFunctions());
}
private static Hash generateTestBlockHash(final long number) {
final byte[] bytes = Long.toString(number).getBytes(UTF_8);
return Hash.hash(Bytes.wrap(bytes));
}
}

@ -11,8 +11,9 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.StubGenesisConfigOptions;
@ -22,6 +23,8 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@ -31,6 +34,9 @@ public class ReferenceTestProtocolSchedules {
private static final BigInteger CHAIN_ID = BigInteger.ONE;
private static final List<String> SPECS_PRIOR_TO_DELETING_EMPTY_ACCOUNTS =
Arrays.asList("Frontier", "Homestead", "EIP150");
public static ReferenceTestProtocolSchedules create() {
final ImmutableMap.Builder<String, ProtocolSchedule> builder = ImmutableMap.builder();
builder.put("Frontier", createSchedule(new StubGenesisConfigOptions()));
@ -77,4 +83,8 @@ public class ReferenceTestProtocolSchedules {
options, CHAIN_ID, Function.identity(), PrivacyParameters.DEFAULT, false)
.createProtocolSchedule();
}
public static boolean shouldClearEmptyAccounts(final String fork) {
return !SPECS_PRIOR_TO_DELETING_EMPTY_ACCOUNTS.contains(fork);
}
}

@ -11,8 +11,9 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.MutableAccount;
@ -31,8 +32,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
/** Represent a mock worldState for testing. */
public class WorldStateMock extends DefaultMutableWorldState {
/** Represent a worldState for testing. */
public class ReferenceTestWorldState extends DefaultMutableWorldState {
public static class AccountMock {
private final long nonce;
@ -41,7 +42,7 @@ public class WorldStateMock extends DefaultMutableWorldState {
private final int version;
private final Map<UInt256, UInt256> storage;
private static final Map<UInt256, UInt256> parseStorage(final Map<String, String> values) {
private static Map<UInt256, UInt256> parseStorage(final Map<String, String> values) {
final Map<UInt256, UInt256> storage = new HashMap<>();
for (final Map.Entry<String, String> entry : values.entrySet()) {
storage.put(UInt256.fromHexString(entry.getKey()), UInt256.fromHexString(entry.getValue()));
@ -87,7 +88,7 @@ public class WorldStateMock extends DefaultMutableWorldState {
}
}
public static void insertAccount(
static void insertAccount(
final WorldUpdater updater, final Address address, final AccountMock toCopy) {
final MutableAccount account = updater.getOrCreate(address).getMutable();
account.setNonce(toCopy.getNonce());
@ -100,8 +101,8 @@ public class WorldStateMock extends DefaultMutableWorldState {
}
@JsonCreator
public static WorldStateMock create(final Map<String, AccountMock> accounts) {
final WorldStateMock worldState = new WorldStateMock();
public static ReferenceTestWorldState create(final Map<String, AccountMock> accounts) {
final ReferenceTestWorldState worldState = new ReferenceTestWorldState();
final WorldUpdater updater = worldState.updater();
for (final Map.Entry<String, AccountMock> entry : accounts.entrySet()) {
@ -112,7 +113,7 @@ public class WorldStateMock extends DefaultMutableWorldState {
return worldState;
}
private WorldStateMock() {
public ReferenceTestWorldState() {
super(
new WorldStateKeyValueStorage(new InMemoryKeyValueStorage()),
new WorldStatePreimageKeyValueStorage(new InMemoryKeyValueStorage()));

@ -11,8 +11,9 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1.PrivateKey;
@ -42,10 +43,11 @@ import org.apache.tuweni.bytes.Bytes32;
* <li>in the state test json, gas, value and data for the transaction are arrays. This is how
* state tests deal with milestone versioning: for a given milestone, the actual value to use
* is defined by the indexes of the "post" section of the json. Those indexes are passed to
* this class in {@link #get(Indexes)}.
* this class in {@link #get(GeneralStateTestCaseSpec.Indexes)}.
* <li>the signature of the transaction is not provided in the json directly. Instead, the private
* key of the sender is provided, and the transaction must thus be signed (also in {@link
* #get(Indexes)}) through {@link Transaction.Builder#signAndBuild(KeyPair)}.
* #get(GeneralStateTestCaseSpec.Indexes)}) through {@link
* Transaction.Builder#signAndBuild(KeyPair)}.
* </ul>
*/
public class StateTestVersionedTransaction {
@ -60,7 +62,17 @@ public class StateTestVersionedTransaction {
private final List<Wei> values;
private final List<Bytes> payloads;
/** Constructor for populating a mock account with json data. */
/**
* Constructor for populating a mock transaction with json data.
*
* @param nonce Nonce of the mock transaction.
* @param gasPrice Gas price of the mock transaction.
* @param gasLimit Gas Limit of the mock transaction.
* @param to Recipient account of the mock transaction.
* @param value Amount of ether transferred in the mock transaction.
* @param secretKey Secret Key of the mock transaction.
* @param data Call data of the mock transaction.
*/
@JsonCreator
public StateTestVersionedTransaction(
@JsonProperty("nonce") final String nonce,

@ -11,10 +11,10 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.vm;
package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.ethereum.core.BlockHeaderMock;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.WorldState;
@ -39,20 +39,20 @@ public class VMReferenceTestCaseSpec {
private final Gas finalGas;
private final WorldStateMock initialWorldState;
private final ReferenceTestWorldState initialWorldState;
private final boolean exceptionalHaltExpected;
private final WorldStateMock finalWorldState;
private final ReferenceTestWorldState finalWorldState;
@JsonCreator
public VMReferenceTestCaseSpec(
@JsonProperty("exec") final EnvironmentInformation exec,
@JsonProperty("env") final BlockHeaderMock env,
@JsonProperty("env") final ReferenceTestEnv env,
@JsonProperty("gas") final String finalGas,
@JsonProperty("out") final String out,
@JsonProperty("pre") final WorldStateMock initialWorldState,
@JsonProperty("post") final WorldStateMock finalWorldState) {
@JsonProperty("pre") final ReferenceTestWorldState initialWorldState,
@JsonProperty("post") final ReferenceTestWorldState finalWorldState) {
this.exec = exec;
this.initialWorldState = initialWorldState;
this.initialWorldState.persist();
@ -113,7 +113,11 @@ public class VMReferenceTestCaseSpec {
return out;
}
/** @return True if this test case should expect the VM to exceptionally halt; otherwise false. */
/**
* Returns true if this test case should expect the VM to exceptionally halt; otherwise false.
*
* @return if an exceptional halt is expected
*/
public boolean isExceptionHaltExpected() {
return exceptionalHaltExpected;
}
Loading…
Cancel
Save