Skip to content

Commit

Permalink
Fix E2E tests in TokenUpdatePrecompileSuite (#9625)
Browse files Browse the repository at this point in the history
Signed-off-by: Miroslav Gatsanoga <miroslav.gatsanoga@limechain.tech>
Signed-off-by: Petar Tonev <petar.tonev@limechain.tech>
Co-authored-by: Miroslav Gatsanoga <miroslav.gatsanoga@limechain.tech>
Signed-off-by: Nick Poorman <nick@swirldslabs.com>
  • Loading branch information
2 people authored and nickpoorman committed Nov 22, 2023
1 parent 4167287 commit 22563e8
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

package com.hedera.node.app.service.contract.impl.exec.scope;

import static com.hedera.hapi.node.base.ResponseCodeEnum.FAIL_INVALID;
import static com.hedera.hapi.node.base.ResponseCodeEnum.SUCCESS;
import static java.util.Objects.requireNonNull;

import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.Key;
import com.hedera.hapi.node.base.NftID;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.base.Transaction;
import com.hedera.hapi.node.contract.ContractFunctionResult;
import com.hedera.hapi.node.state.token.Account;
Expand Down Expand Up @@ -114,12 +114,15 @@ public HandleSystemContractOperations(@NonNull final HandleContext context) {
* {@inheritDoc}
*/
@Override
public void externalizeResult(@NonNull final ContractFunctionResult result, @NonNull final ResultStatus status) {
public void externalizeResult(
@NonNull final ContractFunctionResult result,
@NonNull final ResultStatus status,
@NonNull final ResponseCodeEnum responseStatus) {
final var childRecordBuilder = context.addChildRecordBuilder(ContractCallRecordBuilder.class);
childRecordBuilder
.transaction(Transaction.DEFAULT)
.contractID(result.contractID())
.status(status == ResultStatus.IS_ERROR ? FAIL_INVALID : SUCCESS)
.status(status == ResultStatus.IS_ERROR ? responseStatus : SUCCESS)
.contractCallResult(result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.Key;
import com.hedera.hapi.node.base.NftID;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.contract.ContractFunctionResult;
import com.hedera.hapi.node.state.token.Account;
import com.hedera.hapi.node.state.token.Nft;
Expand Down Expand Up @@ -104,7 +105,10 @@ public QuerySystemContractOperations(@NonNull final QueryContext queryContext) {
* {@inheritDoc}
*/
@Override
public void externalizeResult(@NonNull final ContractFunctionResult result, @NonNull final ResultStatus status) {
public void externalizeResult(
@NonNull final ContractFunctionResult result,
@NonNull final ResultStatus status,
@NonNull final ResponseCodeEnum responseStatus) {
// no-op
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.Key;
import com.hedera.hapi.node.base.NftID;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.contract.ContractFunctionResult;
import com.hedera.hapi.node.state.token.Account;
import com.hedera.hapi.node.state.token.Nft;
Expand Down Expand Up @@ -110,7 +111,10 @@ <T> T dispatch(
* @param result contract function result
* @param status whether the result is success or an error
*/
void externalizeResult(@NonNull final ContractFunctionResult result, @NonNull final ResultStatus status);
void externalizeResult(
@NonNull final ContractFunctionResult result,
@NonNull final ResultStatus status,
@NonNull final ResponseCodeEnum responseStatus);

/**
* Returns the {@Link ExchangeRate} for the current consensus time. This will enable the translation from hbars
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.hedera.node.app.service.contract.impl.exec.systemcontracts;

import static com.hedera.hapi.node.base.ResponseCodeEnum.FAIL_INVALID;
import static com.hedera.hapi.node.base.ResponseCodeEnum.SUCCESS;
import static com.hedera.node.app.service.contract.impl.exec.scope.HandleHederaOperations.ZERO_ENTROPY;
import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmContractId;
import static com.hedera.node.app.service.contract.impl.utils.SystemContractUtils.contractFunctionResultFailedFor;
Expand Down Expand Up @@ -107,7 +108,9 @@ void createSuccessfulRecord(
requireNonNull(contractID);
var updater = (ProxyWorldUpdater) frame.getWorldUpdater();
updater.externalizeSystemContractResults(
contractFunctionResultSuccessFor(gasRequirement, randomNum, contractID), ResultStatus.IS_SUCCESS);
contractFunctionResultSuccessFor(gasRequirement, randomNum, contractID),
ResultStatus.IS_SUCCESS,
SUCCESS);
}
}

Expand All @@ -119,7 +122,9 @@ void createFailedRecord(
contractFunctionResultFailedFor(gasRequirement, errorMsg, contractID);
var updater = (ProxyWorldUpdater) frame.getWorldUpdater();
updater.externalizeSystemContractResults(
contractFunctionResultFailedFor(gasRequirement, errorMsg, contractID), ResultStatus.IS_ERROR);
contractFunctionResultFailedFor(gasRequirement, errorMsg, contractID),
ResultStatus.IS_ERROR,
FAIL_INVALID);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts;

import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID;
import static com.hedera.hapi.node.base.ResponseCodeEnum.SUCCESS;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_PRECOMPILE_ADDRESS;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCall.PricedResult.gasOnly;
import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmContractId;
Expand All @@ -38,7 +39,7 @@
*/
public abstract class AbstractNonRevertibleTokenViewCall extends AbstractHtsCall {
@Nullable
private final Token token;
protected final Token token;

protected AbstractNonRevertibleTokenViewCall(
@NonNull final SystemContractGasCalculator gasCalculator,
Expand All @@ -64,7 +65,8 @@ protected AbstractNonRevertibleTokenViewCall(
.systemOperations()
.externalizeResult(
contractFunctionResultSuccessFor(gasRequirement, output, contractID),
SystemContractUtils.ResultStatus.IS_SUCCESS);
SystemContractUtils.ResultStatus.IS_SUCCESS,
SUCCESS);

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,34 @@

package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokenkey;

import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID;
import static com.hedera.hapi.node.base.ResponseCodeEnum.KEY_NOT_PROVIDED;
import static com.hedera.hapi.node.base.ResponseCodeEnum.SUCCESS;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HederaSystemContract.FullResult.revertResult;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HederaSystemContract.FullResult.successResult;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_PRECOMPILE_ADDRESS;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCall.PricedResult.gasOnly;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.TokenTupleUtils.keyTupleFor;
import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokenkey.TokenKeyTranslator.TOKEN_KEY;
import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmContractId;
import static com.hedera.node.app.service.contract.impl.utils.SystemContractUtils.contractFunctionResultFailedFor;
import static com.hedera.node.app.service.contract.impl.utils.SystemContractUtils.contractFunctionResultSuccessFor;
import static java.util.Objects.requireNonNull;

import com.hedera.hapi.node.base.ContractID;
import com.hedera.hapi.node.base.Key;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.state.token.Token;
import com.hedera.node.app.service.contract.impl.exec.gas.SystemContractGasCalculator;
import com.hedera.node.app.service.contract.impl.exec.systemcontracts.HederaSystemContract.FullResult;
import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AbstractNonRevertibleTokenViewCall;
import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater;
import com.hedera.node.app.service.contract.impl.utils.SystemContractUtils;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import org.apache.tuweni.bytes.Bytes;
import org.hyperledger.besu.datatypes.Address;

public class TokenKeyCall extends AbstractNonRevertibleTokenViewCall {
private final Key key;
Expand All @@ -55,7 +67,7 @@ public TokenKeyCall(
protected @NonNull FullResult resultOfViewingToken(@NonNull final Token token) {
requireNonNull(token);
if (key == null) {
return fullResultsFor(SUCCESS, gasCalculator.viewGasRequirement(), Key.DEFAULT);
return fullResultsFor(CONTRACT_REVERT_EXECUTED, gasCalculator.viewGasRequirement(), Key.DEFAULT);
}
return fullResultsFor(SUCCESS, gasCalculator.viewGasRequirement(), key);
}
Expand All @@ -75,4 +87,45 @@ public TokenKeyCall(
return successResult(
TOKEN_KEY.getOutputs().encodeElements(status.protoOrdinal(), keyTupleFor(key)), gasRequirement);
}

@Override
public @NonNull PricedResult execute() {
PricedResult result;
long gasRequirement;
Bytes output;
ContractID contractID = asEvmContractId(Address.fromHexString(HTS_PRECOMPILE_ADDRESS));
if (token == null) {
result = gasOnly(viewCallResultWith(INVALID_TOKEN_ID, gasCalculator.viewGasRequirement()));

gasRequirement = result.fullResult().gasRequirement();
enhancement
.systemOperations()
.externalizeResult(
contractFunctionResultFailedFor(gasRequirement, INVALID_TOKEN_ID.toString(), contractID),
SystemContractUtils.ResultStatus.IS_ERROR,
INVALID_TOKEN_ID);
} else if (key == null) {
result = gasOnly(viewCallResultWith(KEY_NOT_PROVIDED, gasCalculator.viewGasRequirement()));

gasRequirement = result.fullResult().gasRequirement();
enhancement
.systemOperations()
.externalizeResult(
contractFunctionResultFailedFor(gasRequirement, KEY_NOT_PROVIDED.toString(), contractID),
SystemContractUtils.ResultStatus.IS_ERROR,
KEY_NOT_PROVIDED);
} else {
result = gasOnly(resultOfViewingToken(token));

gasRequirement = result.fullResult().gasRequirement();
output = result.fullResult().result().getOutput();
enhancement
.systemOperations()
.externalizeResult(
contractFunctionResultSuccessFor(gasRequirement, output, contractID),
SystemContractUtils.ResultStatus.IS_SUCCESS,
SUCCESS);
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ public HtsCall callFrom(@NonNull final HtsCallAttempt attempt) {
}

private Key getTokenKey(Token token, int keyType) throws InvalidTransactionException {
if (token == null) {
return null;
}
return switch (keyType) {
case 1 -> token.adminKey();
case 2 -> token.kycKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.ContractID;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.contract.ContractCreateTransactionBody;
import com.hedera.hapi.node.contract.ContractFunctionResult;
import com.hedera.hapi.node.transaction.ExchangeRate;
Expand Down Expand Up @@ -270,7 +271,10 @@ Optional<ExceptionalHaltReason> tryTransfer(
* @param result The result of the system contract call
* @param status Whether the result is an error
*/
void externalizeSystemContractResults(@NonNull final ContractFunctionResult result, ResultStatus status);
void externalizeSystemContractResults(
@NonNull final ContractFunctionResult result,
ResultStatus status,
@NonNull ResponseCodeEnum responseStatus);

/**
* Returns the {@link ExchangeRate} for the current consensus timestamp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.ContractID;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.contract.ContractCreateTransactionBody;
import com.hedera.hapi.node.contract.ContractFunctionResult;
import com.hedera.hapi.node.transaction.ExchangeRate;
Expand Down Expand Up @@ -448,8 +449,10 @@ public void commit() {
*/
@Override
public void externalizeSystemContractResults(
@NonNull final ContractFunctionResult result, final ResultStatus status) {
enhancement.systemOperations().externalizeResult(result, status);
@NonNull final ContractFunctionResult result,
final ResultStatus status,
@NonNull ResponseCodeEnum responseStatus) {
enhancement.systemOperations().externalizeResult(result, status, responseStatus);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void externalizeSuccessfulResultTest() {
given(recordBuilder.contractID(ContractID.DEFAULT)).willReturn(recordBuilder);

// when
subject.externalizeResult(contractFunctionResult, ResultStatus.IS_SUCCESS);
subject.externalizeResult(contractFunctionResult, ResultStatus.IS_SUCCESS, ResponseCodeEnum.SUCCESS);

// then
verify(recordBuilder).contractID(ContractID.DEFAULT);
Expand All @@ -159,7 +159,7 @@ void externalizeFailedResultTest() {
given(recordBuilder.contractID(ContractID.DEFAULT)).willReturn(recordBuilder);

// when
subject.externalizeResult(contractFunctionResult, ResultStatus.IS_ERROR);
subject.externalizeResult(contractFunctionResult, ResultStatus.IS_ERROR, ResponseCodeEnum.FAIL_INVALID);

// then
verify(recordBuilder).contractID(ContractID.DEFAULT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.NftID;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.base.TimestampSeconds;
import com.hedera.hapi.node.base.TokenRelationship;
import com.hedera.hapi.node.contract.ContractFunctionResult;
Expand Down Expand Up @@ -100,7 +101,8 @@ void doesNotSupportAnyMutations() {
assertThrows(
UnsupportedOperationException.class, () -> subject.activeSignatureTestWith(MOCK_VERIFICATION_STRATEGY));

assertDoesNotThrow(() -> subject.externalizeResult(ContractFunctionResult.DEFAULT, ResultStatus.IS_SUCCESS));
assertDoesNotThrow(() -> subject.externalizeResult(
ContractFunctionResult.DEFAULT, ResultStatus.IS_SUCCESS, ResponseCodeEnum.SUCCESS));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.ContractID;
import com.hedera.hapi.node.base.ResponseCodeEnum;
import com.hedera.hapi.node.contract.ContractCreateTransactionBody;
import com.hedera.node.app.service.contract.impl.exec.failure.CustomExceptionalHaltReason;
import com.hedera.node.app.service.contract.impl.exec.scope.HederaNativeOperations;
Expand Down Expand Up @@ -501,8 +502,10 @@ void externalizeSystemContractResultTest() {
var contractFunctionResult = SystemContractUtils.contractFunctionResultSuccessFor(
0, org.apache.tuweni.bytes.Bytes.EMPTY, ContractID.DEFAULT);

subject.externalizeSystemContractResults(contractFunctionResult, ResultStatus.IS_SUCCESS);
verify(systemContractOperations).externalizeResult(contractFunctionResult, ResultStatus.IS_SUCCESS);
subject.externalizeSystemContractResults(
contractFunctionResult, ResultStatus.IS_SUCCESS, ResponseCodeEnum.SUCCESS);
verify(systemContractOperations)
.externalizeResult(contractFunctionResult, ResultStatus.IS_SUCCESS, ResponseCodeEnum.SUCCESS);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import static com.hederahashgraph.api.proto.java.TokenType.FUNGIBLE_COMMON;

import com.google.protobuf.ByteString;
import com.hedera.services.bdd.junit.HapiTest;
import com.hedera.services.bdd.junit.HapiTestSuite;
import com.hedera.services.bdd.spec.HapiSpec;
import com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts;
Expand Down Expand Up @@ -116,6 +117,7 @@ List<HapiSpec> negativeCases() {
getTokenKeyForNonFungibleNegative());
}

@HapiTest
private HapiSpec updateTokenWithInvalidKeyValues() {
final AtomicReference<TokenID> vanillaTokenID = new AtomicReference<>();
return defaultHapiSpec("updateTokenWithInvalidKeyValues")
Expand Down Expand Up @@ -163,6 +165,7 @@ private HapiSpec updateTokenWithInvalidKeyValues() {
.then(sourcing(() -> emptyChildRecordsCheck(UPDATE_TXN, CONTRACT_REVERT_EXECUTED)));
}

@HapiTest
public HapiSpec updateNftTokenKeysWithWrongTokenIdAndMissingAdminKey() {
final AtomicReference<TokenID> nftToken = new AtomicReference<>();
return defaultHapiSpec("updateNftTokenKeysWithWrongTokenIdAndMissingAdminKey")
Expand Down Expand Up @@ -241,6 +244,7 @@ public HapiSpec updateNftTokenKeysWithWrongTokenIdAndMissingAdminKey() {
TransactionRecordAsserts.recordWith().status(TOKEN_IS_IMMUTABLE)))));
}

@HapiTest
public HapiSpec getTokenKeyForNonFungibleNegative() {
final AtomicReference<TokenID> nftToken = new AtomicReference<>();
return defaultHapiSpec("getTokenKeyForNonFungibleNegative")
Expand Down

0 comments on commit 22563e8

Please sign in to comment.