From 3e7a54850b211d88f64db68ba45c6ad65198f05d Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Sat, 13 Oct 2018 06:44:30 +1000 Subject: [PATCH] [NC-1685] Improve tests for BlockHashOperation (#47) * Introduce MessageFrameTestFixture to make it easier to test EVM operations. * Add unit tests for BlockHashOperation. --- .../mainnet/TransactionProcessor.java | 6 +- .../core/MessageFrameTestFixture.java | 184 ++++++++++++++++++ .../ethereum/core/TestCodeExecutor.java | 11 +- .../vm/operations/BlockHashOperationTest.java | 96 +++++++++ .../ethereum/vm/DebugOperationTracerTest.java | 29 +-- .../pantheon/ethereum/vm/TestBlockchain.java | 43 ++-- .../operations/ExtCodeHashOperationTest.java | 25 +-- 7 files changed, 326 insertions(+), 68 deletions(-) create mode 100644 ethereum/core/src/test-support/java/net/consensys/pantheon/ethereum/core/MessageFrameTestFixture.java create mode 100644 ethereum/core/src/test/java/net/consensys/pantheon/ethereum/vm/operations/BlockHashOperationTest.java diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/TransactionProcessor.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/TransactionProcessor.java index e97b638888..8219037274 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/TransactionProcessor.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/TransactionProcessor.java @@ -92,7 +92,8 @@ public interface TransactionProcessor { * @param worldState The current world state * @param blockHeader The current block header * @param transaction The transaction to process - * @param miningBeneficiary the address which is to receive the transaction fee + * @param miningBeneficiary The address which is to receive the transaction fee + * @param blockHashLookup The {@link BlockHashLookup} to use for BLOCKHASH operations * @return the transaction result */ default Result processTransaction( @@ -120,7 +121,8 @@ public interface TransactionProcessor { * @param blockHeader The current block header * @param transaction The transaction to process * @param operationTracer The tracer to record results of each EVM operation - * @param miningBeneficiary the address which is to receive the transaction fee + * @param miningBeneficiary The address which is to receive the transaction fee + * @param blockHashLookup The {@link BlockHashLookup} to use for BLOCKHASH operations * @return the transaction result */ Result processTransaction( diff --git a/ethereum/core/src/test-support/java/net/consensys/pantheon/ethereum/core/MessageFrameTestFixture.java b/ethereum/core/src/test-support/java/net/consensys/pantheon/ethereum/core/MessageFrameTestFixture.java new file mode 100644 index 0000000000..9f3e5a82f7 --- /dev/null +++ b/ethereum/core/src/test-support/java/net/consensys/pantheon/ethereum/core/MessageFrameTestFixture.java @@ -0,0 +1,184 @@ +package net.consensys.pantheon.ethereum.core; + +import tech.pegasys.pantheon.ethereum.chain.Blockchain; +import tech.pegasys.pantheon.ethereum.core.Address; +import tech.pegasys.pantheon.ethereum.core.AddressHelpers; +import tech.pegasys.pantheon.ethereum.core.BlockHeader; +import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture; +import tech.pegasys.pantheon.ethereum.core.Gas; +import tech.pegasys.pantheon.ethereum.core.MutableWorldState; +import tech.pegasys.pantheon.ethereum.core.Wei; +import tech.pegasys.pantheon.ethereum.core.WorldUpdater; +import tech.pegasys.pantheon.ethereum.vm.BlockHashLookup; +import tech.pegasys.pantheon.ethereum.vm.Code; +import tech.pegasys.pantheon.ethereum.vm.MessageFrame; +import tech.pegasys.pantheon.ethereum.vm.MessageFrame.Type; +import tech.pegasys.pantheon.util.bytes.Bytes32; +import tech.pegasys.pantheon.util.bytes.BytesValue; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.List; +import java.util.Optional; + +public class MessageFrameTestFixture { + + private static final Address DEFAUT_ADDRESS = AddressHelpers.ofValue(244259721); + + private Type type = Type.MESSAGE_CALL; + private Deque messageFrameStack = new ArrayDeque<>(); + private Optional blockchain = Optional.empty(); + private Optional worldState = Optional.empty(); + private Gas initialGas = Gas.MAX_VALUE; + private Address address = DEFAUT_ADDRESS; + private Address sender = DEFAUT_ADDRESS; + private Address originator = DEFAUT_ADDRESS; + private Address contract = DEFAUT_ADDRESS; + private Wei gasPrice = Wei.ZERO; + private Wei value = Wei.ZERO; + private BytesValue inputData = BytesValue.EMPTY; + private Code code = new Code(BytesValue.EMPTY); + private final List stackItems = new ArrayList<>(); + private Optional blockHeader = Optional.empty(); + private int depth = 0; + private Optional blockHashLookup = Optional.empty(); + private ExecutionContextTestFixture executionContextTestFixture; + + public MessageFrameTestFixture type(final Type type) { + this.type = type; + return this; + } + + public MessageFrameTestFixture messageFrameStack(final Deque messageFrameStack) { + this.messageFrameStack = messageFrameStack; + return this; + } + + public MessageFrameTestFixture blockchain(final Blockchain blockchain) { + this.blockchain = Optional.of(blockchain); + return this; + } + + public MessageFrameTestFixture worldState(final WorldUpdater worldState) { + this.worldState = Optional.of(worldState); + return this; + } + + public MessageFrameTestFixture worldState(final MutableWorldState worldState) { + this.worldState = Optional.of(worldState.updater()); + return this; + } + + public MessageFrameTestFixture initialGas(final Gas initialGas) { + this.initialGas = initialGas; + return this; + } + + public MessageFrameTestFixture sender(final Address sender) { + this.sender = sender; + return this; + } + + public MessageFrameTestFixture address(final Address address) { + this.address = address; + return this; + } + + public MessageFrameTestFixture originator(final Address originator) { + this.originator = originator; + return this; + } + + public MessageFrameTestFixture contract(final Address contract) { + this.contract = contract; + return this; + } + + public MessageFrameTestFixture gasPrice(final Wei gasPrice) { + this.gasPrice = gasPrice; + return this; + } + + public MessageFrameTestFixture value(final Wei value) { + this.value = value; + return this; + } + + public MessageFrameTestFixture inputData(final BytesValue inputData) { + this.inputData = inputData; + return this; + } + + public MessageFrameTestFixture code(final Code code) { + this.code = code; + return this; + } + + public MessageFrameTestFixture blockHeader(final BlockHeader blockHeader) { + this.blockHeader = Optional.of(blockHeader); + return this; + } + + public MessageFrameTestFixture depth(final int depth) { + this.depth = depth; + return this; + } + + public MessageFrameTestFixture pushStackItem(final Bytes32 item) { + stackItems.add(item); + return this; + } + + public MessageFrameTestFixture blockHashLookup(final BlockHashLookup blockHashLookup) { + this.blockHashLookup = Optional.of(blockHashLookup); + return this; + } + + public MessageFrame build() { + final Blockchain blockchain = this.blockchain.orElseGet(this::createDefaultBlockchain); + final BlockHeader blockHeader = + this.blockHeader.orElseGet(() -> blockchain.getBlockHeader(0).get()); + final MessageFrame frame = + MessageFrame.builder() + .type(type) + .messageFrameStack(messageFrameStack) + .blockchain(blockchain) + .worldState(worldState.orElseGet(this::createDefaultWorldState)) + .initialGas(initialGas) + .address(address) + .originator(originator) + .gasPrice(gasPrice) + .inputData(inputData) + .sender(sender) + .value(value) + .apparentValue(value) + .contract(contract) + .code(code) + .blockHeader(blockHeader) + .depth(depth) + .completer(c -> {}) + .miningBeneficiary(blockHeader.getCoinbase()) + .blockHashLookup( + blockHashLookup.orElseGet(() -> new BlockHashLookup(blockHeader, blockchain))) + .build(); + stackItems.forEach(frame::pushStackItem); + return frame; + } + + private WorldUpdater createDefaultWorldState() { + return getOrCreateExecutionContextTestFixture().getStateArchive().getMutable().updater(); + } + + private Blockchain createDefaultBlockchain() { + return getOrCreateExecutionContextTestFixture().getBlockchain(); + } + + private ExecutionContextTestFixture getOrCreateExecutionContextTestFixture() { + // Avoid creating a test fixture if the test supplies the blockchain and worldstate. + if (executionContextTestFixture == null) { + executionContextTestFixture = new ExecutionContextTestFixture(); + } + return executionContextTestFixture; + } +} diff --git a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java index 28cc016ed7..a36a56a0af 100644 --- a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java +++ b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java @@ -6,10 +6,8 @@ import tech.pegasys.pantheon.ethereum.mainnet.MainnetMessageCallProcessor; import tech.pegasys.pantheon.ethereum.mainnet.PrecompileContractRegistry; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; -import tech.pegasys.pantheon.ethereum.vm.BlockHashLookup; import tech.pegasys.pantheon.ethereum.vm.Code; import tech.pegasys.pantheon.ethereum.vm.MessageFrame; -import tech.pegasys.pantheon.ethereum.vm.MessageFrame.Type; import tech.pegasys.pantheon.ethereum.vm.OperationTracer; import tech.pegasys.pantheon.util.bytes.BytesValue; @@ -18,6 +16,8 @@ import java.util.ArrayDeque; import java.util.Deque; import java.util.function.Consumer; +import net.consensys.pantheon.ethereum.core.MessageFrameTestFixture; + public class TestCodeExecutor { private final ExecutionContextTestFixture fixture; @@ -50,8 +50,7 @@ public class TestCodeExecutor { .nonce(0) .build(); final MessageFrame initialFrame = - MessageFrame.builder() - .type(Type.MESSAGE_CALL) + new MessageFrameTestFixture() .messageFrameStack(messageFrameStack) .blockchain(fixture.getBlockchain()) .worldState(worldState) @@ -63,13 +62,9 @@ public class TestCodeExecutor { .inputData(transaction.getPayload()) .sender(SENDER_ADDRESS) .value(transaction.getValue()) - .apparentValue(transaction.getValue()) .code(new Code(BytesValue.fromHexString(code))) .blockHeader(blockHeader) .depth(0) - .completer(c -> {}) - .miningBeneficiary(blockHeader.coinbase) - .blockHashLookup(new BlockHashLookup(blockHeader, fixture.getBlockchain())) .build(); messageFrameStack.addFirst(initialFrame); diff --git a/ethereum/core/src/test/java/net/consensys/pantheon/ethereum/vm/operations/BlockHashOperationTest.java b/ethereum/core/src/test/java/net/consensys/pantheon/ethereum/vm/operations/BlockHashOperationTest.java new file mode 100644 index 0000000000..8e53bef779 --- /dev/null +++ b/ethereum/core/src/test/java/net/consensys/pantheon/ethereum/vm/operations/BlockHashOperationTest.java @@ -0,0 +1,96 @@ +package net.consensys.pantheon.ethereum.vm.operations; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import tech.pegasys.pantheon.ethereum.core.BlockHeader; +import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; +import tech.pegasys.pantheon.ethereum.core.Hash; +import tech.pegasys.pantheon.ethereum.mainnet.FrontierGasCalculator; +import tech.pegasys.pantheon.ethereum.vm.BlockHashLookup; +import tech.pegasys.pantheon.ethereum.vm.MessageFrame; +import tech.pegasys.pantheon.ethereum.vm.operations.BlockHashOperation; +import tech.pegasys.pantheon.util.bytes.Bytes32; +import tech.pegasys.pantheon.util.bytes.BytesValue; +import tech.pegasys.pantheon.util.uint.UInt256; + +import com.google.common.base.Strings; +import net.consensys.pantheon.ethereum.core.MessageFrameTestFixture; +import org.junit.After; +import org.junit.Test; + +public class BlockHashOperationTest { + + private static final int MAXIMUM_COMPLETE_BLOCKS_BEHIND = 256; + private final BlockHashLookup blockHashLookup = mock(BlockHashLookup.class); + private final BlockHashOperation blockHashOperation = + new BlockHashOperation(new FrontierGasCalculator()); + + @After + public void verifyNoUnexpectedHashLookups() { + verifyNoMoreInteractions(blockHashLookup); + } + + @Test + public void shouldReturnZeroWhenArgIsBiggerThanALong() { + assertBlockHash(Bytes32.fromHexString(Strings.repeat("F", 64)), Bytes32.ZERO, 100); + } + + @Test + public void shouldReturnZeroWhenCurrentBlockIsGenesis() { + assertBlockHash(Bytes32.ZERO, Bytes32.ZERO, BlockHeader.GENESIS_BLOCK_NUMBER); + } + + @Test + public void shouldReturnZeroWhenRequestedBlockAheadOfCurrent() { + assertBlockHash(250, Bytes32.ZERO, 100); + } + + @Test + public void shouldReturnZeroWhenRequestedBlockTooFarBehindCurrent() { + final int requestedBlock = 10; + // Our block is the one after the chain head (it's a new block), hence the + 1. + final int importingBlockNumber = MAXIMUM_COMPLETE_BLOCKS_BEHIND + requestedBlock + 1; + assertBlockHash(requestedBlock, Bytes32.ZERO, importingBlockNumber); + } + + @Test + public void shouldReturnZeroWhenRequestedBlockGreaterThanImportingBlock() { + assertBlockHash(101, Bytes32.ZERO, 100); + } + + @Test + public void shouldReturnZeroWhenRequestedBlockEqualToImportingBlock() { + assertBlockHash(100, Bytes32.ZERO, 100); + } + + @Test + public void shouldReturnBlockHashUsingLookupFromFrameWhenItIsWithinTheAllowedRange() { + final Hash blockHash = Hash.hash(BytesValue.fromHexString("0x1293487297")); + when(blockHashLookup.getBlockHash(100)).thenReturn(blockHash); + assertBlockHash(100, blockHash, 200); + verify(blockHashLookup).getBlockHash(100); + } + + private void assertBlockHash( + final long requestedBlock, final Bytes32 expectedOutput, final long currentBlockNumber) { + assertBlockHash(UInt256.of(requestedBlock).getBytes(), expectedOutput, currentBlockNumber); + } + + private void assertBlockHash( + final Bytes32 input, final Bytes32 expectedOutput, final long currentBlockNumber) { + final MessageFrame frame = + new MessageFrameTestFixture() + .blockHashLookup(blockHashLookup) + .blockHeader(new BlockHeaderTestFixture().number(currentBlockNumber).buildHeader()) + .pushStackItem(input) + .build(); + blockHashOperation.execute(frame); + final Bytes32 result = frame.popStackItem(); + assertThat(result).isEqualTo(expectedOutput); + assertThat(frame.stackSize()).isZero(); + } +} diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/DebugOperationTracerTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/DebugOperationTracerTest.java index 9c63685753..63319e8b14 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/DebugOperationTracerTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/DebugOperationTracerTest.java @@ -5,11 +5,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static tech.pegasys.pantheon.ethereum.core.AddressHelpers.calculateAddressWithRespectTo; import static tech.pegasys.pantheon.ethereum.vm.ExceptionalHaltReason.INSUFFICIENT_GAS; -import tech.pegasys.pantheon.ethereum.core.Address; -import tech.pegasys.pantheon.ethereum.core.AddressHelpers; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; import tech.pegasys.pantheon.ethereum.core.Gas; @@ -21,15 +18,14 @@ import tech.pegasys.pantheon.ethereum.debug.TraceOptions; import tech.pegasys.pantheon.ethereum.vm.OperationTracer.ExecuteOperation; import tech.pegasys.pantheon.ethereum.vm.ehalt.ExceptionalHaltException; import tech.pegasys.pantheon.util.bytes.Bytes32; -import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.uint.UInt256; -import java.util.ArrayDeque; import java.util.EnumSet; import java.util.Map; import java.util.Optional; import java.util.TreeMap; +import net.consensys.pantheon.ethereum.core.MessageFrameTestFixture; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -189,29 +185,16 @@ public class DebugOperationTracerTest { return tracer.getTraceFrames().get(0); } - private MessageFrame.Builder validMessageFrameBuilder() { + private MessageFrameTestFixture validMessageFrameBuilder() { final BlockHeader blockHeader = new BlockHeaderTestFixture().number(1).buildHeader(); final TestBlockchain blockchain = new TestBlockchain(blockHeader.getNumber()); - return MessageFrame.builder() - .type(MessageFrame.Type.MESSAGE_CALL) - .messageFrameStack(new ArrayDeque<>()) - .blockchain(blockchain) - .worldState(worldUpdater) + return new MessageFrameTestFixture() .initialGas(INITIAL_GAS) - .contract(calculateAddressWithRespectTo(Address.ID, 1)) - .address(calculateAddressWithRespectTo(Address.ID, 2)) - .originator(calculateAddressWithRespectTo(Address.ID, 3)) + .worldState(worldUpdater) .gasPrice(Wei.of(25)) - .inputData(BytesValue.EMPTY) - .sender(calculateAddressWithRespectTo(Address.ID, 4)) - .value(Wei.of(30)) - .apparentValue(Wei.of(35)) - .code(new Code()) .blockHeader(blockHeader) - .depth(DEPTH) - .completer(c -> {}) - .miningBeneficiary(AddressHelpers.ofValue(0)) - .blockHashLookup(new BlockHashLookup(blockHeader, blockchain)); + .blockchain(blockchain) + .depth(DEPTH); } private Map setupStorageForCapture(final MessageFrame frame) { diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/TestBlockchain.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/TestBlockchain.java index 4c02a15c12..bd472964d4 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/TestBlockchain.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/TestBlockchain.java @@ -23,14 +23,23 @@ import java.util.Optional; /** * A blockchain mock for the Ethereum reference tests. * - *

The only method this class is used for is {@link TestBlockchain#getBlockHashByNumber} The - * Ethereum reference tests for VM exection (VMTests) and transaction processing (GeneralStateTests) - * require a block's hash to be to be the hash of the string of it's block number. + *

Operations which would lead to non-deterministic behaviour if executed while processing + * transactions throw {@link NonDeterministicOperationException}. For example all methods that + * lookup blocks by number since the block being processed may not be on the canonical chain but + * that must not affect the execution of its transactions. + * + *

The Ethereum reference tests for VM exection (VMTests) and transaction processing + * (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 { // Maximum number of blocks prior to the chain head that can be retrieved by hash. private static final long MAXIMUM_BLOCKS_BEHIND_HEAD = 256; + private static final String NUMBER_LOOKUP_ERROR = + "Blocks must not be looked up by number in the EVM. The block being processed may not be on the canonical chain."; + private static final String CHAIN_HEAD_ERROR = + "Chain head is inherently non-deterministic. The block currently being processed should be treated as the chain head."; private final Map hashToHeader = new HashMap<>(); public TestBlockchain() { @@ -58,32 +67,32 @@ public class TestBlockchain implements Blockchain { @Override public Optional getBlockHashByNumber(final long number) { - return Optional.of(generateTestBlockHash(number)); + throw new NonDeterministicOperationException(NUMBER_LOOKUP_ERROR); } @Override public ChainHead getChainHead() { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException(CHAIN_HEAD_ERROR); } @Override public long getChainHeadBlockNumber() { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException(CHAIN_HEAD_ERROR); } @Override public Hash getChainHeadHash() { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException(CHAIN_HEAD_ERROR); } @Override public Optional getTransactionLocation(final Hash transactionHash) { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException("Transaction location may be different on forks"); } @Override public Optional getBlockHeader(final long blockNumber) { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException(NUMBER_LOOKUP_ERROR); } @Override @@ -93,31 +102,41 @@ public class TestBlockchain implements Blockchain { @Override public Optional getBlockBody(final Hash blockHeaderHash) { + // Deterministic, but just not implemented. throw new UnsupportedOperationException(); } @Override public Optional> getTxReceipts(final Hash blockHeaderHash) { + // Deterministic, but just not implemented. throw new UnsupportedOperationException(); } @Override public Optional getTotalDifficultyByHash(final Hash blockHeaderHash) { + // Deterministic, but just not implemented. throw new UnsupportedOperationException(); } @Override public Optional getTransactionByHash(final Hash transactionHash) { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException( + "Which transactions are on the chain may vary on different forks"); } @Override public long observeBlockAdded(final BlockAddedObserver observer) { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException("Listening for new blocks is not deterministic"); } @Override public boolean removeObserver(final long observerId) { - throw new UnsupportedOperationException(); + throw new NonDeterministicOperationException("Listening for new blocks is not deterministic"); + } + + public static class NonDeterministicOperationException extends RuntimeException { + public NonDeterministicOperationException(final String message) { + super(message); + } } } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperationTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperationTest.java index 2bb86d58ac..78a070d9ad 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperationTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperationTest.java @@ -14,10 +14,7 @@ import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.core.WorldUpdater; import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.mainnet.ConstantinopleGasCalculator; -import tech.pegasys.pantheon.ethereum.vm.BlockHashLookup; -import tech.pegasys.pantheon.ethereum.vm.Code; import tech.pegasys.pantheon.ethereum.vm.MessageFrame; -import tech.pegasys.pantheon.ethereum.vm.MessageFrame.Type; import tech.pegasys.pantheon.ethereum.vm.Words; import tech.pegasys.pantheon.ethereum.worldstate.KeyValueStorageWorldStateStorage; import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage; @@ -25,13 +22,11 @@ import tech.pegasys.pantheon.util.bytes.Bytes32; import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.uint.UInt256; -import java.util.ArrayDeque; - +import net.consensys.pantheon.ethereum.core.MessageFrameTestFixture; import org.junit.Test; public class ExtCodeHashOperationTest { - private static final Address ADDRESS1 = AddressHelpers.ofValue(11111111); private static final Address REQUESTED_ADDRESS = AddressHelpers.ofValue(22222222); private final Blockchain blockchain = mock(Blockchain.class); @@ -108,26 +103,10 @@ public class ExtCodeHashOperationTest { private MessageFrame createMessageFrame(final Bytes32 stackItem) { final BlockHeader blockHeader = new BlockHeaderTestFixture().buildHeader(); final MessageFrame frame = - new MessageFrame.Builder() - .type(Type.MESSAGE_CALL) - .initialGas(Gas.MAX_VALUE) - .inputData(BytesValue.EMPTY) - .depth(1) - .gasPrice(Wei.ZERO) - .contract(ADDRESS1) - .address(ADDRESS1) - .originator(ADDRESS1) - .sender(ADDRESS1) + new MessageFrameTestFixture() .worldState(worldStateUpdater) - .messageFrameStack(new ArrayDeque<>()) .blockHeader(blockHeader) - .value(Wei.ZERO) - .apparentValue(Wei.ZERO) - .code(new Code(BytesValue.EMPTY)) .blockchain(blockchain) - .completer(messageFrame -> {}) - .miningBeneficiary(AddressHelpers.ofValue(0)) - .blockHashLookup(new BlockHashLookup(blockHeader, blockchain)) .build(); frame.pushStackItem(stackItem);