-
Notifications
You must be signed in to change notification settings - Fork 134
Hedera-app 0.65 #11921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hedera-app 0.65 #11921
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,20 +4,9 @@ | |
|
|
||
| import static com.hedera.hapi.streams.ContractActionType.PRECOMPILE; | ||
| import static com.hedera.hapi.streams.ContractActionType.SYSTEM; | ||
| import static com.hedera.node.app.service.contract.impl.exec.failure.CustomExceptionalHaltReason.INSUFFICIENT_CHILD_RECORDS; | ||
| import static com.hedera.node.app.service.contract.impl.exec.failure.CustomExceptionalHaltReason.INVALID_CONTRACT_ID; | ||
| import static com.hedera.node.app.service.contract.impl.exec.failure.CustomExceptionalHaltReason.INVALID_SIGNATURE; | ||
| import static com.hedera.node.app.service.contract.impl.exec.failure.CustomExceptionalHaltReason.*; | ||
|
Check notice on line 7 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.create.CreateCommons.createMethodsSet; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.acquiredSenderAuthorizationViaDelegateCall; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.alreadyHalted; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.incrementOpsDuration; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.isPrecompileEnabled; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.isTopLevelTransaction; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.proxyUpdaterFor; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.recordBuilderFor; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.setPropagatedCallFailure; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.transfersValue; | ||
| import static com.hedera.node.app.service.contract.impl.hevm.HederaOpsDuration.MULTIPLIER_FACTOR; | ||
| import static com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils.*; | ||
|
Check notice on line 9 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| import static com.hedera.node.app.service.contract.impl.hevm.HevmPropagatedCallFailure.MISSING_RECEIVER_SIGNATURE; | ||
| import static com.hedera.node.app.service.contract.impl.hevm.HevmPropagatedCallFailure.RESULT_CANNOT_BE_EXTERNALIZED; | ||
| import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.numberOfLongZero; | ||
|
|
@@ -29,20 +18,18 @@ | |
| import com.hedera.node.app.service.contract.impl.exec.ActionSidecarContentTracer; | ||
| import com.hedera.node.app.service.contract.impl.exec.AddressChecks; | ||
| import com.hedera.node.app.service.contract.impl.exec.FeatureFlags; | ||
| import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; | ||
| import com.hedera.node.app.service.contract.impl.exec.systemcontracts.HederaSystemContract; | ||
| import com.hedera.node.app.service.contract.impl.exec.tracers.AddOnEvmActionTracer; | ||
| import com.hedera.node.app.service.contract.impl.hevm.HederaOpsDuration; | ||
| import com.hedera.node.app.service.contract.impl.exec.utils.FrameUtils; | ||
| import com.hedera.node.app.service.contract.impl.state.ProxyEvmContract; | ||
| import com.hedera.node.app.service.contract.impl.state.ProxyWorldUpdater; | ||
| import edu.umd.cs.findbugs.annotations.NonNull; | ||
| import edu.umd.cs.findbugs.annotations.Nullable; | ||
| import jakarta.annotation.Nonnull; | ||
| import java.util.Arrays; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
| import org.apache.tuweni.bytes.Bytes; | ||
| import org.hiero.mirror.web3.common.ContractCallContext; | ||
| import org.hiero.mirror.web3.evm.contracts.execution.traceability.OpcodeActionTracer; | ||
| import org.hyperledger.besu.datatypes.Address; | ||
| import org.hyperledger.besu.evm.EVM; | ||
| import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; | ||
|
|
@@ -65,22 +52,20 @@ | |
| * and the core {@link MessageCallProcessor#process(MessageFrame, OperationTracer)} logic we inherit. | ||
| * | ||
| * Copy of the class from hedera-app. The differences with it are: | ||
| * | ||
| * - It sets the gasRequirement for a system contract in the ContractCallContext. | ||
| * - It sets the current Map with system contracts coming from hedera.app inside {@link OpcodeActionTracer} | ||
| * - It calls {@link AddOnEvmActionTracer#tracePrecompileCall(MessageFrame, long, Bytes)} instead of | ||
| * {@link AddOnEvmActionTracer#tracePrecompileResult(MessageFrame, ContractActionType)} for precompiles. | ||
| * - It calls {@link ActionSidecarContentTracer#tracePrecompileCall(MessageFrame, long, Bytes)} instead of | ||
| * {@link ActionSidecarContentTracer#tracePrecompileResult(MessageFrame, ContractActionType)} for precompiles. | ||
| * The reasons are that we need to pass the gasRequirement to the tracer and that | ||
| * {@link org.hiero.mirror.web3.evm.contracts.execution.traceability.OpcodeActionTracer} is | ||
| * added as an addOnTracer. The {@link AddOnEvmActionTracer#tracePrecompileCall(MessageFrame, long, Bytes)} method | ||
| * added as an addOnTracer. The {@link ActionSidecarContentTracer#tracePrecompileCall(MessageFrame, long, Bytes)} method | ||
| * delegates the call to the list of addOnTracers, where the {@link org.hiero.mirror.web3.evm.contracts.execution.traceability.OpcodeActionTracer} is stored. | ||
| */ | ||
| public class CustomMessageCallProcessor extends MessageCallProcessor { | ||
| private final FeatureFlags featureFlags; | ||
| private final AddressChecks addressChecks; | ||
| private final PrecompileContractRegistry precompiles; | ||
| private final Map<Address, HederaSystemContract> systemContracts; | ||
| private final HederaOpsDuration hederaOpsDuration; | ||
| private final ContractMetrics contractMetrics; | ||
|
|
||
| private enum ForLazyCreation { | ||
| YES, | ||
|
|
@@ -96,18 +81,18 @@ | |
| * @param systemContracts the Hedera system contracts | ||
| */ | ||
| public CustomMessageCallProcessor( | ||
| @NonNull final EVM evm, | ||
| @NonNull final FeatureFlags featureFlags, | ||
| @NonNull final PrecompileContractRegistry precompiles, | ||
| @NonNull final AddressChecks addressChecks, | ||
| @NonNull final Map<Address, HederaSystemContract> systemContracts, | ||
| @NonNull final HederaOpsDuration hederaOpsDuration) { | ||
| @Nonnull final EVM evm, | ||
| @Nonnull final FeatureFlags featureFlags, | ||
| @Nonnull final PrecompileContractRegistry precompiles, | ||
| @Nonnull final AddressChecks addressChecks, | ||
| @Nonnull final Map<Address, HederaSystemContract> systemContracts, | ||
| @Nonnull final ContractMetrics contractMetrics) { | ||
|
Check notice on line 89 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| super(evm, precompiles); | ||
| this.featureFlags = Objects.requireNonNull(featureFlags); | ||
| this.precompiles = Objects.requireNonNull(precompiles); | ||
| this.addressChecks = Objects.requireNonNull(addressChecks); | ||
| this.systemContracts = Objects.requireNonNull(systemContracts); | ||
| this.hederaOpsDuration = Objects.requireNonNull(hederaOpsDuration); | ||
| this.contractMetrics = Objects.requireNonNull(contractMetrics); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -128,7 +113,7 @@ | |
| * @param tracer the operation tracer | ||
| */ | ||
| @Override | ||
| public void start(@NonNull final MessageFrame frame, @NonNull final OperationTracer tracer) { | ||
| public void start(@Nonnull final MessageFrame frame, @Nonnull final OperationTracer tracer) { | ||
|
Check notice on line 116 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| final var codeAddress = frame.getContractAddress(); | ||
| // This must be done first as the system contract address range overlaps with system | ||
| // accounts. Note that unlike EVM precompiles, we do allow sending value "to" Hedera | ||
|
|
@@ -144,10 +129,6 @@ | |
| return; | ||
| } | ||
| } | ||
|
|
||
| if (tracer instanceof final OpcodeActionTracer opcodeActionTracer) { | ||
| opcodeActionTracer.setSystemContracts(systemContracts); | ||
| } | ||
| doExecuteSystemContract(systemContracts.get(codeAddress), codeAddress, frame, tracer); | ||
| return; | ||
| } | ||
|
|
@@ -223,27 +204,37 @@ | |
| } | ||
|
|
||
| private void handleNonExtantSystemAccount( | ||
| @NonNull final MessageFrame frame, @NonNull final OperationTracer tracer) { | ||
| @Nonnull final MessageFrame frame, @Nonnull final OperationTracer tracer) { | ||
| final PrecompileContractResult result = PrecompileContractResult.success(Bytes.EMPTY); | ||
| frame.clearGasRemaining(); | ||
| finishPrecompileExecution(frame, result, PRECOMPILE, (ActionSidecarContentTracer) tracer); | ||
| } | ||
|
|
||
| private void doExecutePrecompile( | ||
| @NonNull final PrecompiledContract precompile, | ||
| @NonNull final MessageFrame frame, | ||
| @NonNull final OperationTracer tracer) { | ||
| @Nonnull final PrecompiledContract precompile, | ||
| @Nonnull final MessageFrame frame, | ||
| @Nonnull final OperationTracer tracer) { | ||
| final var gasRequirement = precompile.gasRequirement(frame.getInputData()); | ||
| final PrecompileContractResult result; | ||
| if (frame.getRemainingGas() < gasRequirement) { | ||
| result = PrecompileContractResult.halt(Bytes.EMPTY, Optional.of(INSUFFICIENT_GAS)); | ||
| } else { | ||
| frame.decrementRemainingGas(gasRequirement); | ||
| incrementOpsDuration( | ||
| frame, gasRequirement * hederaOpsDuration.precompileDurationMultiplier() / MULTIPLIER_FACTOR); | ||
| result = precompile.computePrecompile(frame.getInputData(), frame); | ||
| if (result.isRefundGas()) { | ||
| frame.incrementRemainingGas(gasRequirement); | ||
|
|
||
| final var opsDurationCounter = FrameUtils.opsDurationCounter(frame); | ||
|
Check notice on line 224 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| final var opsDurationSchedule = opsDurationCounter.schedule(); | ||
| final var opsDurationCost = gasRequirement | ||
| * opsDurationSchedule.precompileGasBasedDurationMultiplier() | ||
| / opsDurationSchedule.multipliersDenominator(); | ||
| if (!opsDurationCounter.tryConsumeOpsDurationUnits(opsDurationCost)) { | ||
|
Check notice on line 229 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| result = PrecompileContractResult.halt(Bytes.EMPTY, Optional.of(OPS_DURATION_LIMIT_REACHED)); | ||
| } else { | ||
| contractMetrics.opsDurationMetrics().recordPrecompileOpsDuration(precompile.getName(), opsDurationCost); | ||
|
|
||
| result = precompile.computePrecompile(frame.getInputData(), frame); | ||
| if (result.isRefundGas()) { | ||
|
Check warning on line 235 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| frame.incrementRemainingGas(gasRequirement); | ||
| } | ||
| } | ||
| } | ||
| // We must always call tracePrecompileResult() to ensure the tracer is in a consistent | ||
|
|
@@ -263,10 +254,10 @@ | |
| * @param tracer the operation tracer | ||
| */ | ||
| private void doExecuteSystemContract( | ||
| @NonNull final HederaSystemContract systemContract, | ||
| @NonNull final Address systemContractAddress, | ||
| @NonNull final MessageFrame frame, | ||
| @NonNull final OperationTracer tracer) { | ||
| @Nonnull final HederaSystemContract systemContract, | ||
| @Nonnull final Address systemContractAddress, | ||
|
Check notice on line 258 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| @Nonnull final MessageFrame frame, | ||
| @Nonnull final OperationTracer tracer) { | ||
| final var fullResult = systemContract.computeFully( | ||
| ContractID.newBuilder() | ||
| .contractNum(numberOfLongZero(systemContractAddress)) | ||
|
|
@@ -283,20 +274,31 @@ | |
| } else { | ||
| if (!fullResult.isRefundGas()) { | ||
| frame.decrementRemainingGas(gasRequirement); | ||
| incrementOpsDuration( | ||
| frame, | ||
| gasRequirement * hederaOpsDuration.systemContractDurationMultiplier() / MULTIPLIER_FACTOR); | ||
| } | ||
| result = fullResult.result(); | ||
|
|
||
| final var opsDurationCounter = FrameUtils.opsDurationCounter(frame); | ||
| final var opsDurationSchedule = opsDurationCounter.schedule(); | ||
| final var opsDurationCost = gasRequirement | ||
| * opsDurationSchedule.systemContractGasBasedDurationMultiplier() | ||
| / opsDurationSchedule.multipliersDenominator(); | ||
| if (!opsDurationCounter.tryConsumeOpsDurationUnits(opsDurationCost)) { | ||
| result = PrecompileContractResult.halt(Bytes.EMPTY, Optional.of(OPS_DURATION_LIMIT_REACHED)); | ||
| } else { | ||
| contractMetrics | ||
| .opsDurationMetrics() | ||
| .recordSystemContractOpsDuration( | ||
| systemContract.getName(), systemContractAddress.toHexString(), opsDurationCost); | ||
| result = fullResult.result(); | ||
| } | ||
| } | ||
| finishPrecompileExecution(frame, result, SYSTEM, (ActionSidecarContentTracer) tracer); | ||
| } | ||
|
|
||
| private void finishPrecompileExecution( | ||
| @NonNull final MessageFrame frame, | ||
| @NonNull final PrecompileContractResult result, | ||
| @NonNull final ContractActionType type, | ||
| @NonNull final ActionSidecarContentTracer tracer) { | ||
| @Nonnull final MessageFrame frame, | ||
| @Nonnull final PrecompileContractResult result, | ||
| @Nonnull final ContractActionType type, | ||
|
Check warning on line 300 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java
|
||
| @Nonnull final ActionSidecarContentTracer tracer) { | ||
| if (result.getState() == MessageFrame.State.REVERT) { | ||
| frame.setRevertReason(result.getOutput()); | ||
| } else { | ||
|
|
@@ -308,7 +310,7 @@ | |
| } | ||
|
|
||
| private void doTransferValueOrHalt( | ||
| @NonNull final MessageFrame frame, @NonNull final OperationTracer operationTracer) { | ||
| @Nonnull final MessageFrame frame, @Nonnull final OperationTracer operationTracer) { | ||
| final var proxyWorldUpdater = (ProxyWorldUpdater) frame.getWorldUpdater(); | ||
| // Try to lazy-create the recipient address if it doesn't exist | ||
| if (!addressChecks.isPresent(frame.getRecipientAddress(), frame)) { | ||
|
|
@@ -331,31 +333,31 @@ | |
| } | ||
|
|
||
| private void doHaltIfInvalidSystemCall( | ||
| @NonNull final MessageFrame frame, @NonNull final OperationTracer operationTracer) { | ||
| @Nonnull final MessageFrame frame, @Nonnull final OperationTracer operationTracer) { | ||
| if (transfersValue(frame)) { | ||
| doHalt(frame, INVALID_CONTRACT_ID, operationTracer); | ||
| } | ||
| } | ||
|
|
||
| private void doHaltOnFailedLazyCreation( | ||
| @NonNull final MessageFrame frame, | ||
| @NonNull final ExceptionalHaltReason reason, | ||
| @NonNull final OperationTracer tracer) { | ||
| @Nonnull final MessageFrame frame, | ||
| @Nonnull final ExceptionalHaltReason reason, | ||
| @Nonnull final OperationTracer tracer) { | ||
| doHalt(frame, reason, tracer, ForLazyCreation.YES); | ||
| } | ||
|
|
||
| private void doHalt( | ||
| @NonNull final MessageFrame frame, | ||
| @NonNull final ExceptionalHaltReason reason, | ||
| @NonNull final OperationTracer tracer) { | ||
| @Nonnull final MessageFrame frame, | ||
| @Nonnull final ExceptionalHaltReason reason, | ||
| @Nonnull final OperationTracer tracer) { | ||
| doHalt(frame, reason, tracer, ForLazyCreation.NO); | ||
| } | ||
|
|
||
| private void doHalt( | ||
| @NonNull final MessageFrame frame, | ||
| @NonNull final ExceptionalHaltReason reason, | ||
| @Nullable final OperationTracer operationTracer, | ||
| @NonNull final ForLazyCreation forLazyCreation) { | ||
| @Nonnull final MessageFrame frame, | ||
| @Nonnull final ExceptionalHaltReason reason, | ||
| @Nonnull final OperationTracer operationTracer, | ||
| @Nonnull final ForLazyCreation forLazyCreation) { | ||
| frame.setState(EXCEPTIONAL_HALT); | ||
| frame.setExceptionalHaltReason(Optional.of(reason)); | ||
| if (forLazyCreation == ForLazyCreation.YES) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use 0.65.1