diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java index ccabce833a6..caa5cb36724 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java @@ -51,6 +51,7 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.RLP; +import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedAccount; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.log.Log; @@ -265,9 +266,11 @@ static T8nResult runTest( .blobGasPricePerGas(calculateExcessBlobGasForParent(protocolSpec, blockHeader)); long blobGasLimit = protocolSpec.getGasLimitCalculator().currentBlobGasLimit(); - protocolSpec - .getBlockHashProcessor() - .processBlockHashes(blockchain, worldState, referenceTestEnv); + if (!referenceTestEnv.isStateTest()) { + protocolSpec + .getBlockHashProcessor() + .processBlockHashes(blockchain, worldState, referenceTestEnv); + } final WorldUpdater rootWorldStateUpdater = worldState.updater(); List receipts = new ArrayList<>(); @@ -318,13 +321,12 @@ static T8nResult runTest( timer.stop(); if (shouldClearEmptyAccounts(fork)) { - final Account coinbase = worldStateUpdater.getOrCreate(blockHeader.getCoinbase()); - if (coinbase != null && coinbase.isEmpty()) { - worldStateUpdater.deleteAccount(coinbase.getAddress()); - } - final Account txSender = worldStateUpdater.getAccount(transaction.getSender()); - if (txSender != null && txSender.isEmpty()) { - worldStateUpdater.deleteAccount(txSender.getAddress()); + var entries = new ArrayList<>(worldState.getAccumulator().getAccountsToUpdate().entrySet()); + for (var entry : entries) { + DiffBasedAccount updated = entry.getValue().getUpdated(); + if (updated != null && updated.isEmpty()) { + worldState.getAccumulator().deleteAccount(entry.getKey()); + } } } if (result.isInvalid()) { @@ -397,7 +399,9 @@ static T8nResult runTest( // block reward // The max production reward was 5 Eth, longs can hold over 18 Eth. - if (!validTransactions.isEmpty() && (rewardString == null || Long.decode(rewardString) > 0)) { + if (!referenceTestEnv.isStateTest() + && !validTransactions.isEmpty() + && (rewardString == null || Long.decode(rewardString) > 0)) { Wei reward = (rewardString == null) ? protocolSpec.getBlockReward() @@ -408,15 +412,24 @@ static T8nResult runTest( } rootWorldStateUpdater.commit(); - // Invoke the withdrawal processor to handle CL withdrawals. - if (!referenceTestEnv.getWithdrawals().isEmpty()) { - try { - protocolSpec - .getWithdrawalsProcessor() - .ifPresent( - p -> p.processWithdrawals(referenceTestEnv.getWithdrawals(), worldState.updater())); - } catch (RuntimeException re) { - resultObject.put("exception", re.getMessage()); + + if (referenceTestEnv.isStateTest()) { + if (!referenceTestEnv.getWithdrawals().isEmpty()) { + resultObject.put("exception", "withdrawals are not supported in state tests"); + } + } else { + // Invoke the withdrawal processor to handle CL withdrawals. + if (!referenceTestEnv.getWithdrawals().isEmpty()) { + try { + protocolSpec + .getWithdrawalsProcessor() + .ifPresent( + p -> + p.processWithdrawals( + referenceTestEnv.getWithdrawals(), worldState.updater())); + } catch (RuntimeException re) { + resultObject.put("exception", re.getMessage()); + } } } diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java index 378637f3634..1048f6238a2 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java @@ -249,7 +249,8 @@ public CandidateBlock( @JsonProperty("uncleHeaders") final Object uncleHeaders, @JsonProperty("withdrawals") final Object withdrawals, @JsonProperty("depositRequests") final Object depositRequests, - @JsonProperty("withdrawalRequests") final Object withdrawalRequests) { + @JsonProperty("withdrawalRequests") final Object withdrawalRequests, + @JsonProperty("consolidationRequests") final Object consolidationRequests) { boolean blockVaid = true; // The BLOCK__WrongCharAtRLP_0 test has an invalid character in its rlp string. Bytes rlpAttempt = null; diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java index 3cd248e3aef..636e23f8786 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java @@ -83,6 +83,8 @@ Withdrawal asWithdrawal() { private final Bytes32 beaconRoot; + private final boolean isStateTest; + /** * Public constructor. * @@ -120,7 +122,8 @@ public ReferenceTestEnv( @JsonProperty("parentGasLimit") final String parentGasLimit, @JsonProperty("parentGasUsed") final String parentGasUsed, @JsonProperty("parentTimestamp") final String parentTimestamp, - @JsonProperty("parentUncleHash") final String _parentUncleHash) { + @JsonProperty("parentUncleHash") final String _parentUncleHash, + @JsonProperty("isStateTest") final String isStateTest) { super( generateTestBlockHash(previousHash, number), Hash.EMPTY_LIST_HASH, // ommersHash @@ -164,10 +167,16 @@ public ReferenceTestEnv( Map.entry( Long.decode(entry.getKey()), Hash.fromHexString(entry.getValue()))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - this.beaconRoot = - beaconRoot == null - ? (currentBeaconRoot == null ? null : Hash.fromHexString(currentBeaconRoot)) - : Hash.fromHexString(beaconRoot); + if (beaconRoot == null) { + if (currentBeaconRoot == null) { + this.beaconRoot = null; + } else { + this.beaconRoot = Hash.fromHexString(currentBeaconRoot); + } + } else { + this.beaconRoot = Hash.fromHexString(beaconRoot); + } + this.isStateTest = Boolean.parseBoolean(isStateTest); } @Override @@ -239,6 +248,10 @@ public Map getBlockHashes() { return blockHashes; } + public boolean isStateTest() { + return isStateTest; + } + @Override public boolean equals(final Object o) { if (this == o) return true;