diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperation.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperation.java index 2cbfe1beb7..13f4e65295 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperation.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/vm/operations/ExtCodeHashOperation.java @@ -36,7 +36,7 @@ public Gas cost(final MessageFrame frame) { public void execute(final MessageFrame frame) { final Address address = Words.toAddress(frame.popStackItem()); final Account account = frame.getWorldState().get(address); - if (account == null) { + if (account == null || account.isEmpty()) { frame.pushStackItem(Bytes32.ZERO); } else { frame.pushStackItem(account.getCodeHash()); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTest.java index 7349e2f65e..1759bab751 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTest.java @@ -93,6 +93,11 @@ public void constantinople() { milestone("Constantinople"); } + @Test + public void constantinopleFix() { + milestone("ConstantinopleFix"); + } + public void milestone(final String milestone) { final TransactionTestCaseSpec.Expectation expected = spec.expectation(milestone); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTestCaseSpec.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTestCaseSpec.java index 43e7647535..9997c4a015 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTestCaseSpec.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionTestCaseSpec.java @@ -15,6 +15,7 @@ import tech.pegasys.pantheon.util.bytes.BytesValue; import java.util.HashMap; +import java.util.Map; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -61,26 +62,22 @@ public Address getSender() { private final BytesValue rlp; + @SuppressWarnings("unchecked") @JsonCreator - public TransactionTestCaseSpec( - @JsonProperty("Frontier") final Expectation frontierExpectation, - @JsonProperty("Homestead") final Expectation homesteadExpectation, - @JsonProperty("EIP150") final Expectation EIP150Expectation, - @JsonProperty("EIP158") final Expectation EIP158Expectation, - @JsonProperty("Byzantium") final Expectation byzantiumExpectation, - @JsonProperty("Constantinople") final Expectation constantinopleExpectation, - @JsonProperty("rlp") final String rlp) { + public TransactionTestCaseSpec(final Map props) { expectations = new HashMap<>(); - expectations.put("Frontier", frontierExpectation); - expectations.put("Homestead", homesteadExpectation); - expectations.put("EIP150", EIP150Expectation); - expectations.put("EIP158", EIP158Expectation); - expectations.put("Byzantium", byzantiumExpectation); - expectations.put("Constantinople", constantinopleExpectation); + for (final Map.Entry entry : props.entrySet()) { + if ("rlp".equals(entry.getKey())) continue; + + final Map expectation = (Map) entry.getValue(); + expectations.put( + entry.getKey(), + new Expectation((String) expectation.get("hash"), (String) expectation.get("sender"))); + } BytesValue parsedRlp = null; try { - parsedRlp = BytesValue.fromHexString(rlp); + parsedRlp = BytesValue.fromHexString(props.get("rlp").toString()); } catch (final IllegalArgumentException e) { // Some test cases include rlp "hex strings" with invalid characters // In this case, just set rlp to null diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestCaseSpec.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestCaseSpec.java index dd2705e41f..211b385cdc 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestCaseSpec.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestCaseSpec.java @@ -186,6 +186,8 @@ public ParsedExtraData parseExtraData(final BlockHeader header) { @JsonIgnoreProperties({ "expectExceptionByzantium", "expectExceptionConstantinople", + "expectExceptionConstantinopleFix", + "expectExceptionIstanbul", "expectExceptionEIP150", "expectExceptionEIP158", "expectExceptionFrontier", diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestTools.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestTools.java index e0914d59d3..930f11ad07 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestTools.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/BlockchainReferenceTestTools.java @@ -61,7 +61,8 @@ public class BlockchainReferenceTestTools { } // Known bad test. - params.blacklist("RevertPrecompiledTouch_d0g0v0_(EIP158|Byzantium)"); + params.blacklist( + "RevertPrecompiledTouch(_storage)?_d(0|3)g0v0_(EIP158|Byzantium|Constantinople|ConstantinopleFix)"); // Consumes a huge amount of memory params.blacklist( diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/GeneralStateReferenceTestTools.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/GeneralStateReferenceTestTools.java index 3f2a2148c1..684d33a3fc 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/GeneralStateReferenceTestTools.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/GeneralStateReferenceTestTools.java @@ -81,7 +81,8 @@ private static TransactionProcessor transactionProcessor(final String name) { params.blacklistAll(); } // Known incorrect test. - params.blacklist("RevertPrecompiledTouch-(EIP158|Byzantium)"); + params.blacklist( + "RevertPrecompiledTouch(_storage)?-(EIP158|Byzantium|Constantinople|ConstantinopleFix)"); // Gas integer value is too large to construct a valid transaction. params.blacklist("OverflowGasRequire"); // Consumes a huge amount of memory 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 87ea0c56e2..4cb2eb8e89 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 @@ -63,10 +63,16 @@ public void shouldReturnZeroWhenAccountDoesNotExist() { @Test public void shouldReturnHashOfEmptyDataWhenAccountExistsButDoesNotHaveCode() { - worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + worldStateUpdater.getOrCreate(REQUESTED_ADDRESS).setBalance(Wei.of(1)); assertThat(executeOperation(REQUESTED_ADDRESS)).isEqualTo(Hash.EMPTY); } + @Test + public void shouldReturnZeroWhenAccountExistsButIsEmpty() { + worldStateUpdater.getOrCreate(REQUESTED_ADDRESS); + assertThat(executeOperation(REQUESTED_ADDRESS)).isEqualTo(Bytes32.ZERO); + } + @Test public void shouldReturnZeroWhenPrecompiledContractHasNoBalance() { assertThat(executeOperation(Address.ECREC)).isEqualTo(Bytes32.ZERO); diff --git a/ethereum/referencetests/src/test/resources b/ethereum/referencetests/src/test/resources index 420f443477..0327d9f76c 160000 --- a/ethereum/referencetests/src/test/resources +++ b/ethereum/referencetests/src/test/resources @@ -1 +1 @@ -Subproject commit 420f443477caa8516f1f9ee8122fafc3415c0f34 +Subproject commit 0327d9f76ce2a292a99e7a9dfc93627368ce589e