Skip to content
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

Add missing logics and validations from services #8157

Merged
merged 17 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,7 @@ enum ContractMethods implements ContractMethodInterface {
TRANSFER_NFT("transferNFTExternal", 53751),
TRANSFER_NFTS("transferNFTsExternal", 57015),
TRANSFER_TOKEN("transferTokenExternal", 39666),
TRANSFER_TOKENS("transferTokensExternal", 42480),
TRANSFER_TOKENS("transferTokensExternal", 43314),
UNFREEZE_TOKEN("unfreezeTokenExternal", 39323),
WIPE_TOKEN_ACCOUNT("wipeTokenAccountExternal", 39496),
WIPE_NFT_ACCOUNT("wipeTokenAccountNFTExternal", 40394),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,9 @@ OpUsageCtxHelper opUsageCtxHelper(final Store store, final HederaEvmContractAlia
AccessorBasedUsages accessorBasedUsages(
final TokenOpsUsage tokenOpsUsage,
final CryptoOpsUsage cryptoOpsUsage,
final OpUsageCtxHelper opUsageCtxHelper) {
return new AccessorBasedUsages(tokenOpsUsage, cryptoOpsUsage, opUsageCtxHelper);
final OpUsageCtxHelper opUsageCtxHelper,
final MirrorNodeEvmProperties mirrorNodeEvmProperties) {
return new AccessorBasedUsages(tokenOpsUsage, cryptoOpsUsage, opUsageCtxHelper, mirrorNodeEvmProperties);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
import com.hederahashgraph.api.proto.java.Timestamp;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.List;
import java.util.Optional;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
Expand Down Expand Up @@ -72,7 +73,7 @@ protected void executeLazyCreate(final MessageFrame frame, final OperationTracer
.setSeconds(frame.getBlockValues().getTimestamp())
.build();
final var lazyCreateResult =
autoCreationLogic.create(syntheticBalanceChange, timestamp, updater.getStore(), entityAddressSequencer);
autoCreationLogic.create(syntheticBalanceChange, timestamp, updater.getStore(), entityAddressSequencer, List.of(syntheticBalanceChange));
if (lazyCreateResult.getLeft() != ResponseCodeEnum.OK) {
haltFrameAndTraceCreationResult(frame, operationTracer, FAILURE_DURING_LAZY_ACCOUNT_CREATE);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ public class MirrorNodeEvmProperties implements EvmProperties {
@Min(100)
private long rateLimit = 500;

@Getter
@Min(1)
private int feesTokenTransferUsageMultiplier = 380;
zhpetkov marked this conversation as resolved.
Show resolved Hide resolved

public boolean shouldAutoRenewAccounts() {
return autoRenewTargetTypes.contains(EntityType.ACCOUNT);
}
Expand Down Expand Up @@ -300,6 +304,10 @@ SemanticVersion getEvmVersionForBlock(long blockNumber) {
}
}

public int feesTokenTransferUsageMultiplier() {
return feesTokenTransferUsageMultiplier;
}

@Getter
@RequiredArgsConstructor
public enum HederaNetwork {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,14 @@
0L,
balance::toLong,
false,
() -> 0L,

Check warning on line 132 in hedera-mirror-web3/src/main/java/com/hedera/mirror/web3/evm/store/contract/HederaEvmStackedWorldStateUpdater.java

View check run for this annotation

Codecov / codecov/patch

hedera-mirror-web3/src/main/java/com/hedera/mirror/web3/evm/store/contract/HederaEvmStackedWorldStateUpdater.java#L132

Added line #L132 was not covered by tests
0L,
null,
0,
Collections::emptySortedMap,
Collections::emptySortedMap,
Collections::emptySortedSet,
() -> 0,

Check warning on line 139 in hedera-mirror-web3/src/main/java/com/hedera/mirror/web3/evm/store/contract/HederaEvmStackedWorldStateUpdater.java

View check run for this annotation

Codecov / codecov/patch

hedera-mirror-web3/src/main/java/com/hedera/mirror/web3/evm/store/contract/HederaEvmStackedWorldStateUpdater.java#L139

Added line #L139 was not covered by tests
() -> 0,
0,
nonce,
Expand Down Expand Up @@ -223,4 +223,22 @@
store.updateAccount(ghostAcc);
return createAccount(address, 0, Wei.ZERO);
}

public boolean contractIsTokenTreasury(final Address addressOrAlias) {
final var address = mirrorEvmContractAliases.resolveForEvm(addressOrAlias);
com.hedera.services.store.models.Account account = store.getAccount(address, OnMissing.THROW);
return account.getNumTreasuryTitles() > 0;
}

public boolean contractHasAnyBalance(final Address addressOrAlias) {
final var address = mirrorEvmContractAliases.resolveForEvm(addressOrAlias);
com.hedera.services.store.models.Account account = store.getAccount(address, OnMissing.THROW);
return account.getNumPositiveBalances() > 0;
}

public boolean contractOwnsNfts(final Address addressOrAlias) {
final var address = mirrorEvmContractAliases.resolveForEvm(addressOrAlias);
com.hedera.services.store.models.Account account = store.getAccount(address, OnMissing.THROW);
return account.getOwnedNfts() > 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,15 @@

import com.hedera.mirror.web3.evm.store.contract.HederaEvmStackedWorldStateUpdater;
import com.hedera.node.app.service.evm.contracts.operations.HederaExceptionalHaltReason;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.function.BiPredicate;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.internal.Words;
import org.hyperledger.besu.evm.operation.SelfDestructOperation;

import java.util.function.BiPredicate;

/**
* Hedera adapted version of the {@link SelfDestructOperation}.
*
Expand All @@ -42,7 +39,7 @@
* address being destructed
* This class is a copy of HederaSelfDestructOperation from hedera-services mono
*/
public class HederaSelfDestructOperation extends SelfDestructOperation {
public class HederaSelfDestructOperation extends HederaSelfDestructOperationBase {

private final BiPredicate<Address, MessageFrame> addressValidator;

Expand All @@ -63,24 +60,11 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
}
final var beneficiary = updater.get(beneficiaryAddress);

final var exceptionalHaltReason = reasonToHalt(toBeDeleted, beneficiaryAddress);
final var exceptionalHaltReason = reasonToHalt(toBeDeleted, beneficiaryAddress, updater);
if (exceptionalHaltReason != null) {
return reversionWith(beneficiary, exceptionalHaltReason);
}

return super.execute(frame, evm);
}

@Nullable
private ExceptionalHaltReason reasonToHalt(final Address toBeDeleted, final Address beneficiaryAddress) {
if (toBeDeleted.equals(beneficiaryAddress)) {
return HederaExceptionalHaltReason.SELF_DESTRUCT_TO_SELF;
}
return null;
}

private OperationResult reversionWith(final Account beneficiary, final ExceptionalHaltReason reason) {
final long cost = gasCalculator().selfDestructOperationGasCost(beneficiary, Wei.ONE);
return new OperationResult(cost, reason);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.hedera.services.evm.contracts.operations;

import com.hedera.mirror.web3.evm.store.contract.HederaEvmStackedWorldStateUpdater;
import com.hedera.node.app.service.evm.contracts.operations.HederaExceptionalHaltReason;
import edu.umd.cs.findbugs.annotations.Nullable;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.operation.SelfDestructOperation;

public class HederaSelfDestructOperationBase extends SelfDestructOperation {

public HederaSelfDestructOperationBase(final GasCalculator gasCalculator) {
super(gasCalculator);
}

@Nullable
protected ExceptionalHaltReason reasonToHalt(final Address toBeDeleted,
final Address beneficiaryAddress,
final HederaEvmStackedWorldStateUpdater updater) {
if (toBeDeleted.equals(beneficiaryAddress)) {
return HederaExceptionalHaltReason.SELF_DESTRUCT_TO_SELF;
}

if (updater.contractIsTokenTreasury(toBeDeleted)) {
return HederaExceptionalHaltReason.CONTRACT_IS_TREASURY;
}

if (updater.contractHasAnyBalance(toBeDeleted)) {
return HederaExceptionalHaltReason.TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES;
}

if (updater.contractOwnsNfts(toBeDeleted)) {
return HederaExceptionalHaltReason.CONTRACT_STILL_OWNS_NFTS;
}
return null;
}

protected OperationResult reversionWith(final Account beneficiary, final ExceptionalHaltReason reason) {
final long cost = gasCalculator().selfDestructOperationGasCost(beneficiary, Wei.ONE);
return new OperationResult(cost, reason);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,16 @@

import com.hedera.mirror.web3.evm.store.contract.HederaEvmStackedWorldStateUpdater;
import com.hedera.node.app.service.evm.contracts.operations.HederaExceptionalHaltReason;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.internal.Words;
import org.hyperledger.besu.evm.operation.SelfDestructOperation;

import java.util.function.BiPredicate;
import java.util.function.Predicate;

/**
* Hedera adapted version of the {@link SelfDestructOperation}.
*
Expand All @@ -43,7 +40,7 @@
* address being destructed
* This class is a copy of HederaSelfDestructOperationV038 from hedera-services mono
*/
public class HederaSelfDestructOperationV038 extends SelfDestructOperation {
public class HederaSelfDestructOperationV038 extends HederaSelfDestructOperationBase {

private final BiPredicate<Address, MessageFrame> addressValidator;

Expand All @@ -69,24 +66,11 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
}
final var beneficiary = updater.get(beneficiaryAddress);

final var exceptionalHaltReason = reasonToHalt(toBeDeleted, beneficiaryAddress);
final var exceptionalHaltReason = reasonToHalt(toBeDeleted, beneficiaryAddress, updater);
if (exceptionalHaltReason != null) {
return reversionWith(beneficiary, exceptionalHaltReason);
}

return super.execute(frame, evm);
}

@Nullable
private ExceptionalHaltReason reasonToHalt(final Address toBeDeleted, final Address beneficiaryAddress) {
if (toBeDeleted.equals(beneficiaryAddress)) {
return HederaExceptionalHaltReason.SELF_DESTRUCT_TO_SELF;
}
return null;
}

private OperationResult reversionWith(final Account beneficiary, final ExceptionalHaltReason reason) {
final long cost = gasCalculator().selfDestructOperationGasCost(beneficiary, Wei.ONE);
return new OperationResult(cost, reason);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,17 @@

import com.hedera.mirror.web3.evm.store.contract.HederaEvmStackedWorldStateUpdater;
import com.hedera.node.app.service.evm.contracts.operations.HederaExceptionalHaltReason;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.EVM;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.internal.Words;
import org.hyperledger.besu.evm.operation.SelfDestructOperation;

import java.util.function.BiPredicate;
import java.util.function.Predicate;

/**
* Hedera adapted version of the {@link SelfDestructOperation}.
*
Expand All @@ -43,7 +41,7 @@
* address being destructed.
* This class is a copy of HederaSelfDestructOperationV046 from hedera-services mono
*/
public class HederaSelfDestructOperationV046 extends SelfDestructOperation {
public class HederaSelfDestructOperationV046 extends HederaSelfDestructOperationBase {

private final BiPredicate<Address, MessageFrame> addressValidator;
private final Predicate<Address> systemAccountDetector;
Expand All @@ -70,24 +68,11 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
}
final var beneficiary = updater.get(beneficiaryAddress);

final var exceptionalHaltReason = reasonToHalt(toBeDeleted, beneficiaryAddress);
final var exceptionalHaltReason = reasonToHalt(toBeDeleted, beneficiaryAddress, updater);
if (exceptionalHaltReason != null) {
return reversionWith(beneficiary, exceptionalHaltReason);
}

return super.execute(frame, evm);
}

@Nullable
private ExceptionalHaltReason reasonToHalt(final Address toBeDeleted, final Address beneficiaryAddress) {
if (toBeDeleted.equals(beneficiaryAddress)) {
return HederaExceptionalHaltReason.SELF_DESTRUCT_TO_SELF;
}
return null;
}

private OperationResult reversionWith(final Account beneficiary, final ExceptionalHaltReason reason) {
final long cost = gasCalculator().selfDestructOperationGasCost(beneficiary, Wei.ONE);
return new OperationResult(cost, reason);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,24 @@
import static com.hederahashgraph.api.proto.java.HederaFunctionality.TokenUnfreezeAccount;
import static com.hederahashgraph.api.proto.java.HederaFunctionality.TokenUnpause;

import com.hedera.mirror.web3.evm.properties.MirrorNodeEvmProperties;
import com.hedera.services.fees.usage.state.UsageAccumulator;
import com.hedera.services.fees.usage.token.TokenOpsUsage;
import com.hedera.services.hapi.fees.usage.BaseTransactionMeta;
import com.hedera.services.hapi.fees.usage.SigUsage;
import com.hedera.services.hapi.fees.usage.crypto.CryptoOpsUsage;
import com.hedera.services.utils.accessors.TxnAccessor;
import com.hederahashgraph.api.proto.java.HederaFunctionality;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.EnumSet;

/**
* Copied Logic type from hedera-services. Differences with the original:
* 1. Remove FeeSchedule, UtilPrng, File logic
*/
@Singleton
public class AccessorBasedUsages {

public static final long THREE_MONTHS_IN_SECONDS = 7776000L;
Expand All @@ -68,12 +73,18 @@ public class AccessorBasedUsages {
private final TokenOpsUsage tokenOpsUsage;
private final CryptoOpsUsage cryptoOpsUsage;
private final OpUsageCtxHelper opUsageCtxHelper;
private final MirrorNodeEvmProperties mirrorNodeEvmProperties;

@Inject
public AccessorBasedUsages(
TokenOpsUsage tokenOpsUsage, CryptoOpsUsage cryptoOpsUsage, OpUsageCtxHelper opUsageCtxHelper) {
TokenOpsUsage tokenOpsUsage,
CryptoOpsUsage cryptoOpsUsage,
OpUsageCtxHelper opUsageCtxHelper,
MirrorNodeEvmProperties mirrorNodeEvmProperties) {
this.tokenOpsUsage = tokenOpsUsage;
this.cryptoOpsUsage = cryptoOpsUsage;
this.opUsageCtxHelper = opUsageCtxHelper;
this.mirrorNodeEvmProperties = mirrorNodeEvmProperties;
}

public void assess(SigUsage sigUsage, TxnAccessor accessor, UsageAccumulator into) {
Expand Down Expand Up @@ -119,6 +130,7 @@ public boolean supports(HederaFunctionality function) {
private void estimateCryptoTransfer(
SigUsage sigUsage, TxnAccessor accessor, BaseTransactionMeta baseMeta, UsageAccumulator into) {
final var xferMeta = accessor.availXferUsageMeta();
xferMeta.setTokenMultiplier(mirrorNodeEvmProperties.feesTokenTransferUsageMultiplier());
cryptoOpsUsage.cryptoTransferUsage(sigUsage, xferMeta, baseMeta, into);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void doZeroSum(
.setSeconds(Instant.now().getEpochSecond())
.build(),
store,
ids);
ids, changes);
validity = result.getKey();
if (validity == OK && (change.isForToken())) {
validity = hederaTokenStore.tryTokenChange(change);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,13 @@ public TransactionBody.Builder createMint(final MintWrapper mintWrapper) {
return TransactionBody.newBuilder().setTokenMint(builder);
}

public TransactionBody.Builder createHollowAccount(final ByteString alias, final long balance) {
public TransactionBody.Builder createHollowAccount(final ByteString alias, final long balance, final int maxAutoAssociations) {
final var baseBuilder = createAccountBase(balance);
baseBuilder.setKey(asKeyUnchecked(EMPTY_KEY)).setAlias(alias).setMemo(LAZY_MEMO);
baseBuilder
.setKey(asKeyUnchecked(EMPTY_KEY))
.setAlias(alias)
.setMaxAutomaticTokenAssociations(maxAutoAssociations)
.setMemo(LAZY_MEMO);
return TransactionBody.newBuilder().setCryptoCreateAccount(baseBuilder.build());
}

Expand Down