Merge branch 'main' into zkbesu

# Conflicts:
#	.github/workflows/draft-release.yml
This commit is contained in:
Fabio Di Fabio
2025-01-15 11:24:31 +01:00
103 changed files with 5402 additions and 7581 deletions

View File

@@ -21,6 +21,7 @@ import static org.hyperledger.besu.evm.internal.Words.clampedToLong;
import static org.hyperledger.besu.evm.internal.Words.numWords;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.MessageFrame;
@@ -566,4 +567,25 @@ public class FrontierGasCalculator implements GasCalculator {
public long getMinimumTransactionCost() {
return TX_BASE_COST;
}
@Override
public long calculateGasRefund(
final Transaction transaction,
final MessageFrame initialFrame,
final long codeDelegationRefund) {
final long selfDestructRefund =
getSelfDestructRefundAmount() * initialFrame.getSelfDestructs().size();
final long baseRefundGas =
initialFrame.getGasRefund() + selfDestructRefund + codeDelegationRefund;
return refunded(transaction, initialFrame.getRemainingGas(), baseRefundGas);
}
private long refunded(
final Transaction transaction, final long gasRemaining, final long gasRefund) {
// Integer truncation takes care of the floor calculation needed after the divide.
final long maxRefundAllowance =
(transaction.getGasLimit() - gasRemaining) / getMaxRefundQuotient();
final long refundAllowance = Math.min(maxRefundAllowance, gasRefund);
return gasRemaining + refundAllowance;
}
}

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.evm.gascalculator;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.MessageFrame;
@@ -664,4 +665,15 @@ public interface GasCalculator {
default long calculateDelegateCodeGasRefund(final long alreadyExistingAccountSize) {
return 0L;
}
/**
* Calculate the gas refund for a transaction.
*
* @param transaction the transaction
* @param initialFrame the initial frame
* @param codeDelegationRefund the code delegation refund
* @return the gas refund
*/
long calculateGasRefund(
Transaction transaction, MessageFrame initialFrame, long codeDelegationRefund);
}

View File

@@ -16,8 +16,10 @@ package org.hyperledger.besu.evm.precompile;
import org.hyperledger.besu.datatypes.Address;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/** Encapsulates a group of {@link PrecompiledContract}s used together. */
public class PrecompileContractRegistry {
@@ -48,4 +50,13 @@ public class PrecompileContractRegistry {
public void put(final Address address, final PrecompiledContract precompile) {
precompiles.put(address, precompile);
}
/**
* Gets the addresses of the precompiled contracts.
*
* @return the addresses
*/
public Set<Address> getPrecompileAddresses() {
return Collections.unmodifiableSet(precompiles.keySet());
}
}

View File

@@ -30,6 +30,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,8 @@ import org.slf4j.LoggerFactory;
public class MessageCallProcessor extends AbstractMessageProcessor {
private static final Logger LOG = LoggerFactory.getLogger(MessageCallProcessor.class);
private final PrecompileContractRegistry precompiles;
/** The precompiles. */
protected final PrecompileContractRegistry precompiles;
/**
* Instantiates a new Message call processor.
@@ -171,4 +173,14 @@ public class MessageCallProcessor extends AbstractMessageProcessor {
frame.setExceptionalHaltReason(result.getHaltReason());
}
}
/**
* Gets the precompile addresses.
*
* @return the precompile addresses
*/
@VisibleForTesting
public Set<Address> getPrecompileAddresses() {
return precompiles.getPrecompileAddresses();
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright contributors to Besu.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm.processor;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry;
import java.util.Map;
/**
* A message call processor designed specifically for simulation purposes that allows for overriding
* precompile addresses.
*/
public class OverriddenPrecompilesMessageCallProcessor extends MessageCallProcessor {
/**
* Instantiates a new Modifiable precompiles message call processor for simulation.
*
* @param originalProcessor the original processor
* @param precompileOverrides the address overrides
*/
public OverriddenPrecompilesMessageCallProcessor(
final MessageCallProcessor originalProcessor,
final Map<Address, Address> precompileOverrides) {
super(
originalProcessor.evm,
createRegistryWithPrecompileOverrides(originalProcessor.precompiles, precompileOverrides));
}
/**
* Creates a new PrecompileContractRegistry with the specified address overrides.
*
* @param originalRegistry the original precompile contract registry
* @param precompileOverrides the address overrides
* @return a new PrecompileContractRegistry with the overrides applied
*/
private static PrecompileContractRegistry createRegistryWithPrecompileOverrides(
final PrecompileContractRegistry originalRegistry,
final Map<Address, Address> precompileOverrides) {
PrecompileContractRegistry newRegistry = new PrecompileContractRegistry();
for (Address originalAddress : originalRegistry.getPrecompileAddresses()) {
Address effectiveAddress = precompileOverrides.getOrDefault(originalAddress, originalAddress);
newRegistry.put(effectiveAddress, originalRegistry.get(originalAddress));
}
return newRegistry;
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm.gascalculator;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.evm.frame.MessageFrame;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class FrontierGasCalculatorTest {
private final GasCalculator gasCalculator = new FrontierGasCalculator();
@Mock private Transaction transaction;
@Mock private MessageFrame messageFrame;
@Test
void shouldCalculateRefundWithNoSelfDestructs() {
// Arrange
when(messageFrame.getSelfDestructs()).thenReturn(Collections.emptySet());
when(messageFrame.getGasRefund()).thenReturn(1000L);
when(messageFrame.getRemainingGas()).thenReturn(5000L);
when(transaction.getGasLimit()).thenReturn(100000L);
// Act
long refund = gasCalculator.calculateGasRefund(transaction, messageFrame, 500L);
// Assert
assertThat(refund)
.isEqualTo(6500L); // 5000 (remaining) + min(1500 (total refund), 19000 (max allowance))
}
@Test
void shouldCalculateRefundWithMultipleSelfDestructs() {
// Arrange
Set<Address> selfDestructs = new HashSet<>();
selfDestructs.add(Address.wrap(Bytes.random(20)));
selfDestructs.add(Address.wrap(Bytes.random(20)));
when(messageFrame.getSelfDestructs()).thenReturn(selfDestructs);
when(messageFrame.getGasRefund()).thenReturn(1000L);
when(messageFrame.getRemainingGas()).thenReturn(5000L);
when(transaction.getGasLimit()).thenReturn(100000L);
// Act
long refund = gasCalculator.calculateGasRefund(transaction, messageFrame, 500L);
// Assert
assertThat(refund)
.isEqualTo(52500L); // 5000 (remaining) + min(47500 (total refund), 49500 (max allowance))
}
@Test
void shouldRespectMaxRefundAllowance() {
// Arrange
when(messageFrame.getSelfDestructs()).thenReturn(Collections.emptySet());
when(messageFrame.getGasRefund()).thenReturn(100000L);
when(messageFrame.getRemainingGas()).thenReturn(20000L);
when(transaction.getGasLimit()).thenReturn(100000L);
// Act
long refund = gasCalculator.calculateGasRefund(transaction, messageFrame, 1000L);
// Assert
assertThat(refund)
.isEqualTo(60000L); // 20000 (remaining) + min(101000 (total refund), 40000 (max allowance))
}
@Test
void shouldHandleZeroValuesCorrectly() {
// Arrange
when(messageFrame.getSelfDestructs()).thenReturn(Collections.emptySet());
when(messageFrame.getGasRefund()).thenReturn(0L);
when(messageFrame.getRemainingGas()).thenReturn(0L);
when(transaction.getGasLimit()).thenReturn(100000L);
// Act
long refund = gasCalculator.calculateGasRefund(transaction, messageFrame, 0L);
// Assert
assertThat(refund).isEqualTo(0L);
}
}