Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
52aea71
Bump hedera-app to v0.65.1
bilyana-gospodinova Sep 11, 2025
25f78e2
Adapt copied CustomMessageCallProcessor
bilyana-gospodinova Sep 11, 2025
979ddc2
Fix ReadableKVStateBase
bilyana-gospodinova Sep 11, 2025
ad4bc8d
Fix WritableKVStateBase
bilyana-gospodinova Sep 11, 2025
7627f73
Fix ListReadableQueueState
bilyana-gospodinova Sep 11, 2025
bec7b24
Fix ListWritableQueueState
bilyana-gospodinova Sep 11, 2025
c4fa77d
Fix MapReadableKVState
bilyana-gospodinova Sep 11, 2025
bf79a42
Fix MapWritableKVState
bilyana-gospodinova Sep 11, 2025
b3574e9
Fix StateRegistry
bilyana-gospodinova Sep 11, 2025
214aedb
Fix SchemaRegistryImpl
bilyana-gospodinova Sep 11, 2025
69ec9cd
Update changed interface structure in MirrorNodeState
bilyana-gospodinova Sep 11, 2025
43d6aea
Add implementation for FunctionReadableSingletonState
bilyana-gospodinova Sep 11, 2025
6d9e4c0
Implement FunctionWritableSingletonState
bilyana-gospodinova Sep 11, 2025
0ee0c97
Adapt changed interface in ServiceMigratorImpl
bilyana-gospodinova Sep 11, 2025
cc4fd07
Fix AbstractReadableKVState
bilyana-gospodinova Sep 11, 2025
3364833
Set service names to existing readable KV states
bilyana-gospodinova Sep 11, 2025
1e53844
Adapt copied DispatchingEvmFrameState
bilyana-gospodinova Sep 11, 2025
c84066a
Adapt copied ConversionUtils
bilyana-gospodinova Sep 11, 2025
ec2cab7
Fix tech.pegasys dependency issue
bilyana-gospodinova Sep 12, 2025
dcfc102
Add missing state registry keys
bilyana-gospodinova Sep 12, 2025
db9695b
Copy RootProxyWorldUpdater - it is needed for the opcode tracer storage
bilyana-gospodinova Sep 16, 2025
b19e5aa
Adapt opcode tracer after removed pendingStorageUpdates() method
bilyana-gospodinova Sep 16, 2025
a49a391
Cleanup
bilyana-gospodinova Sep 17, 2025
d7f46ba
Copy changes from the Account model
bilyana-gospodinova Sep 17, 2025
41fdbe8
Fix some codacy issues that are not from copied classes.
bilyana-gospodinova Sep 17, 2025
090e1d2
Prevent type case exception in OpcodeActionTracer
bilyana-gospodinova Sep 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/releases-comparator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ jobs:
"com/swirlds/state/spi/WritableKVStateBase.java"
"com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java"
"com/hedera/node/app/service/contract/impl/state/DispatchingEvmFrameState.java"
"com/hedera/node/app/service/contract/impl/state/RootProxyWorldUpdater.java"
"com/hedera/node/app/service/contract/impl/utils/ConversionUtils.java"
"com/hedera/node/app/service/contract/impl/exec/operations/CustomBalanceOperation.java"
)
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ dependencies {
api("com.graphql-java-generator:graphql-java-client-runtime:3.0")
api("com.graphql-java:graphql-java-extended-scalars:24.0")
api("com.graphql-java:graphql-java-extended-validation:24.0")
api("com.hedera.hashgraph:app:0.64.3")
api("com.hedera.hashgraph:app:0.65.1")
api("com.hedera.evm:hedera-evm:0.54.2")
api("com.hedera.hashgraph:hedera-protobuf-java-api:0.63.5")
api("com.hedera.hashgraph:sdk:2.63.0")
Expand Down
109 changes: 102 additions & 7 deletions web3/src/main/java/com/hedera/hapi/node/state/token/Account.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@
* <p>
* This value SHALL NOT be empty if this account is "sender" for any
* pending airdrop, and SHALL be empty otherwise.
* @param numberPendingAirdrops <b>(35)</b> A number of pending airdrops.
* <p>
* This count SHALL be used to calculate rent _without_ walking the linked
* list of pending airdrops associated to this account via the
* `head_pending_airdrop_id` field.</p><br/>
* This value MUST be updated for every airdrop, clam, or cancel transaction
* that designates this account as a receiver.<br/>
* This number MUST always match the count of entries in the "list"
* identified by `head_pending_airdrop_id`.
* @param numberHooksInUse <b>(36)</b> The number of hooks currently in use on this account.
* @param firstHookId <b>(37)</b> If the account has more than zero hooks in use, the id of the first hook in its
* doubly-linked list of hooks.
* @param numberLambdaStorageSlots <b>(38)</b> The number of storage slots in use by this account's lambdas.
*/
public record Account(
@Nullable AccountID accountId,
Expand Down Expand Up @@ -126,7 +139,10 @@ public record Account(
boolean expiredAndPendingRemoval,
@Nonnull Bytes firstContractStorageKey,
@Nullable PendingAirdropId headPendingAirdropId,
long numberPendingAirdrops) {
long numberPendingAirdrops,
long numberHooksInUse,
long firstHookId,
long numberLambdaStorageSlots) {
/** Protobuf codec for reading and writing in protobuf format */
public static final Codec<Account> PROTOBUF = new com.hedera.hapi.node.state.token.codec.AccountProtoCodec();
/** JSON codec for reading and writing in JSON format */
Expand Down Expand Up @@ -172,7 +188,10 @@ public Account(
boolean expiredAndPendingRemoval,
Bytes firstContractStorageKey,
PendingAirdropId headPendingAirdropId,
long numberPendingAirdrops) {
long numberPendingAirdrops,
long numberHooksInUse,
long firstHookId,
long numberLambdaStorageSlots) {
this(
accountId,
alias,
Expand Down Expand Up @@ -207,7 +226,10 @@ public Account(
expiredAndPendingRemoval,
firstContractStorageKey,
headPendingAirdropId,
numberPendingAirdrops);
numberPendingAirdrops,
numberHooksInUse,
firstHookId,
numberLambdaStorageSlots);
}

/**
Expand Down Expand Up @@ -349,6 +371,15 @@ public int hashCode() {
if (numberPendingAirdrops != DEFAULT.numberPendingAirdrops) {
result = 31 * result + Long.hashCode(numberPendingAirdrops);
}
if (numberHooksInUse != DEFAULT.numberHooksInUse) {
result = 31 * result + Long.hashCode(numberHooksInUse);
}
if (firstHookId != DEFAULT.firstHookId) {
result = 31 * result + Long.hashCode(firstHookId);
}
if (numberLambdaStorageSlots != DEFAULT.numberLambdaStorageSlots) {
result = 31 * result + Long.hashCode(numberLambdaStorageSlots);
}
long hashCode = result;
// Shifts: 30, 27, 16, 20, 5, 18, 10, 24, 30
hashCode += hashCode << 30;
Expand Down Expand Up @@ -521,7 +552,16 @@ public boolean equals(Object that) {
if (headPendingAirdropId != null && !headPendingAirdropId.equals(thatObj.headPendingAirdropId)) {
return false;
}
return numberPendingAirdrops == thatObj.numberPendingAirdrops;
if (numberPendingAirdrops != thatObj.numberPendingAirdrops) {
return false;
}
if (numberHooksInUse != thatObj.numberHooksInUse) {
return false;
}
if (firstHookId != thatObj.firstHookId) {
return false;
}
return numberLambdaStorageSlots == thatObj.numberLambdaStorageSlots;
}

@Override
Expand Down Expand Up @@ -900,7 +940,10 @@ public Builder copyBuilder() {
expiredAndPendingRemoval,
firstContractStorageKey,
headPendingAirdropId,
numberPendingAirdrops);
numberPendingAirdrops,
numberHooksInUse,
firstHookId,
numberLambdaStorageSlots);
}

public long tinybarBalance() {
Expand Down Expand Up @@ -1090,6 +1133,12 @@ public static final class Builder {

private long numberPendingAirdrops = 0;

private long numberHooksInUse = 0;

private long firstHookId = 0;

private long numberLambdaStorageSlots = 0;

/**
* Create an empty builder
*/
Expand Down Expand Up @@ -1163,6 +1212,10 @@ public Builder() {}
* pending airdrop, and SHALL be empty otherwise.
* @param numberPendingAirdrops <b>(35)</b> The number of pending airdrops owned by the account. This number is used to collect rent
* for the account.
* @param numberHooksInUse <b>(36)</b> The number of hooks currently in use on this account.
* @param firstHookId <b>(37)</b> If the account has more than zero hooks in use, the id of the first hook in its
* doubly-linked list of hooks.
* @param numberLambdaStorageSlots <b>(38)</b> The number of storage slots in use by this account's lambdas.
*/
@SuppressWarnings("java:S107")
public Builder(
Expand Down Expand Up @@ -1199,7 +1252,10 @@ public Builder(
boolean expiredAndPendingRemoval,
Bytes firstContractStorageKey,
PendingAirdropId headPendingAirdropId,
long numberPendingAirdrops) {
long numberPendingAirdrops,
long numberHooksInUse,
long firstHookId,
long numberLambdaStorageSlots) {
this.accountId = accountId;
this.alias = alias != null ? alias : Bytes.EMPTY;
this.key = key;
Expand Down Expand Up @@ -1238,6 +1294,9 @@ public Builder(
this.firstContractStorageKey = firstContractStorageKey != null ? firstContractStorageKey : Bytes.EMPTY;
this.headPendingAirdropId = headPendingAirdropId;
this.numberPendingAirdrops = numberPendingAirdrops;
this.numberHooksInUse = numberHooksInUse;
this.firstHookId = firstHookId;
this.numberLambdaStorageSlots = numberLambdaStorageSlots;
}

/**
Expand Down Expand Up @@ -1280,7 +1339,10 @@ public Account build() {
expiredAndPendingRemoval,
firstContractStorageKey,
headPendingAirdropId,
numberPendingAirdrops);
numberPendingAirdrops,
numberHooksInUse,
firstHookId,
numberLambdaStorageSlots);
}

/**
Expand Down Expand Up @@ -1876,5 +1938,38 @@ public Builder numberPendingAirdrops(long numberPendingAirdrops) {
this.numberPendingAirdrops = numberPendingAirdrops;
return this;
}

/**
* <b>(36)</b> The number of hooks currently in use on this account.
*
* @param numberHooksInUse value to set
* @return builder to continue building with
*/
public Builder numberHooksInUse(long numberHooksInUse) {
this.numberHooksInUse = numberHooksInUse;
return this;
}

/**
* <b>(37)</b> If the account has more than zero hooks in use, the id of the first hook in its doubly-linked list of hooks.
*
* @param firstHookId value to set
* @return builder to continue building with
*/
public Builder firstHookId(long firstHookId) {
this.firstHookId = firstHookId;
return this;
}

/**
* <b>(38)</b> The number of storage slots in use by this account's lambdas.
*
* @param numberLambdaStorageSlots value to set
* @return builder to continue building with
*/
public Builder numberLambdaStorageSlots(long numberLambdaStorageSlots) {
this.numberLambdaStorageSlots = numberLambdaStorageSlots;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@
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.OPS_DURATION_LIMIT_REACHED;
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.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;
Expand All @@ -29,9 +28,9 @@
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;
Expand All @@ -42,7 +41,6 @@
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;
Expand All @@ -67,7 +65,6 @@
* 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.
* The reasons are that we need to pass the gasRequirement to the tracer and that
Expand All @@ -80,7 +77,7 @@
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,
Expand All @@ -101,13 +98,13 @@
@NonNull final PrecompileContractRegistry precompiles,
@NonNull final AddressChecks addressChecks,
@NonNull final Map<Address, HederaSystemContract> systemContracts,
@NonNull final HederaOpsDuration hederaOpsDuration) {
@NonNull final ContractMetrics contractMetrics) {

Check notice on line 101 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java#L101

Expected @param tag for 'contractMetrics'.
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);
}

/**
Expand Down Expand Up @@ -144,10 +141,6 @@
return;
}
}

if (tracer instanceof final OpcodeActionTracer opcodeActionTracer) {
opcodeActionTracer.setSystemContracts(systemContracts);
}
doExecuteSystemContract(systemContracts.get(codeAddress), codeAddress, frame, tracer);
return;
}
Expand Down Expand Up @@ -239,11 +232,21 @@
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);
final var opsDurationSchedule = opsDurationCounter.schedule();
final var opsDurationCost = gasRequirement
* opsDurationSchedule.precompileGasBasedDurationMultiplier()
/ opsDurationSchedule.multipliersDenominator();
if (!opsDurationCounter.tryConsumeOpsDurationUnits(opsDurationCost)) {

Check notice on line 241 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java#L241

Avoid if (x != y) ..; else ..;
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 247 in web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

web3/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/CustomMessageCallProcessor.java#L247

Nested if-else depth is 2 (max allowed is 1).
frame.incrementRemainingGas(gasRequirement);
}
}
}
// We must always call tracePrecompileResult() to ensure the tracer is in a consistent
Expand Down Expand Up @@ -283,11 +286,22 @@
} 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);
}
Expand Down
Loading
Loading