diff --git a/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/validation/ExpiryValidator.java b/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/validation/ExpiryValidator.java index 78788fa57590..ff989bad00d2 100644 --- a/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/validation/ExpiryValidator.java +++ b/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/validation/ExpiryValidator.java @@ -16,6 +16,7 @@ package com.hedera.node.app.spi.validation; +import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.base.ResponseCodeEnum; import com.hedera.node.app.spi.workflows.HandleException; import com.hedera.node.app.spi.workflows.TransactionHandler; @@ -31,16 +32,18 @@ public interface ExpiryValidator { * Validates the expiry metadata for an attempt to create an entity. * @param entityCanSelfFundRenewal whether the entity can self-fund its own auto-renewal * @param creationMetadata the expiry metadata for the attempted creation - * @param isForTopicCreation if the expiry metadata is for topic creation. + * @param functionality the HederaFunctionality that is being attempted * This is only needed until differential testing is completed to comply with - * mono-service respoinse codes. + * mono-service response codes. * * @return the expiry metadata that will result from the creation * @throws HandleException if the metadata is invalid */ @NonNull ExpiryMeta resolveCreationAttempt( - boolean entityCanSelfFundRenewal, @NonNull ExpiryMeta creationMetadata, final boolean isForTopicCreation); + boolean entityCanSelfFundRenewal, + @NonNull final ExpiryMeta creationMetadata, + @NonNull final HederaFunctionality functionality); /** * Validates the expiry metadata for an attempt to update an entity, and returns the @@ -49,11 +52,13 @@ ExpiryMeta resolveCreationAttempt( * * @param currentMetadata the current expiry metadata for the entity * @param updateMetadata the expiry metadata for the attempted update + * @param isForTokenUpdate if the expiry metadata is for token update * @return the expiry metadata that will result from the update * @throws HandleException if the metadata is invalid */ @NonNull - ExpiryMeta resolveUpdateAttempt(@NonNull ExpiryMeta currentMetadata, @NonNull ExpiryMeta updateMetadata); + ExpiryMeta resolveUpdateAttempt( + @NonNull ExpiryMeta currentMetadata, @NonNull ExpiryMeta updateMetadata, boolean isForTokenUpdate); /** * Gets the expiration status of an entity based on the {@link EntityType}. diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImpl.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImpl.java index e1e504823142..1c869ca599be 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImpl.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImpl.java @@ -16,6 +16,7 @@ package com.hedera.node.app.workflows.handle.validation; +import static com.hedera.hapi.node.base.ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE; import static com.hedera.hapi.node.base.ResponseCodeEnum.BAD_ENCODING; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_EXPIRATION_TIME; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_RENEWAL_PERIOD; @@ -100,10 +101,11 @@ public void validateExpiry(long expiry) { @Override public void validateAutoRenewPeriod(long autoRenewPeriod) { final var ledgerConfig = context.configuration().getConfigData(LedgerConfig.class); + validateTrue(autoRenewPeriod > 0, INVALID_RENEWAL_PERIOD); validateTrue( autoRenewPeriod >= ledgerConfig.autoRenewPeriodMinDuration() && autoRenewPeriod <= ledgerConfig.autoRenewPeriodMaxDuration(), - INVALID_RENEWAL_PERIOD); + AUTORENEW_DURATION_NOT_IN_RANGE); } private void validateKeyAtLevel(@NonNull final Key key, final int level) { diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImpl.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImpl.java index 880a8405ac07..53290aaad5bb 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImpl.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImpl.java @@ -17,9 +17,11 @@ package com.hedera.node.app.workflows.handle.validation; import static com.hedera.hapi.node.base.ResponseCodeEnum.ACCOUNT_EXPIRED_AND_PENDING_REMOVAL; +import static com.hedera.hapi.node.base.ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE; import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_EXPIRED_AND_PENDING_REMOVAL; import static com.hedera.hapi.node.base.ResponseCodeEnum.EXPIRATION_REDUCTION_NOT_ALLOWED; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_RENEWAL_PERIOD; import static com.hedera.hapi.node.base.ResponseCodeEnum.OK; import static com.hedera.node.app.service.mono.fees.calculation.FeeCalcUtils.clampedAdd; import static com.hedera.node.app.spi.workflows.HandleException.validateFalse; @@ -27,6 +29,7 @@ import static java.util.Objects.requireNonNull; import com.hedera.hapi.node.base.AccountID; +import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.base.ResponseCodeEnum; import com.hedera.node.app.service.evm.exceptions.InvalidTransactionException; import com.hedera.node.app.service.mono.pbj.PbjConverter; @@ -62,7 +65,7 @@ public ExpiryValidatorImpl(@NonNull final HandleContext context) { public ExpiryMeta resolveCreationAttempt( final boolean entityCanSelfFundRenewal, @NonNull final ExpiryMeta creationMeta, - final boolean isForTopicCreate) { + @NonNull final HederaFunctionality functionality) { if (creationMeta.hasAutoRenewAccountId()) { validateAutoRenewAccount(creationMeta.autoRenewAccountId()); } @@ -74,33 +77,52 @@ public ExpiryMeta resolveCreationAttempt( if (hasCompleteAutoRenewSpec(entityCanSelfFundRenewal, creationMeta)) { effectiveExpiry = clampedAdd(context.consensusNow().getEpochSecond(), creationMeta.autoRenewPeriod()); } - // In mono-service this check is done first for topic creation. // To maintain same behaviour for differential testing this condition is needed. // FUTURE: This condition should be removed after differential testing is done - if (isForTopicCreate) { + if (functionality == HederaFunctionality.CONSENSUS_CREATE_TOPIC) { + // In mono-service this check is done first for topic creation. context.attributeValidator().validateExpiry(effectiveExpiry); // Even if the effective expiry is valid, we still also require any explicit auto-renew period to be valid - if (creationMeta.hasAutoRenewPeriod()) { - context.attributeValidator().validateAutoRenewPeriod(creationMeta.autoRenewPeriod()); + validateAutoRenew(creationMeta); + } else if (functionality == HederaFunctionality.TOKEN_CREATE) { + // In mono-service, INVALID_RENEWAL_PERIOD is thrown for token creation and update + // if the autoRenewPeriod is not in range. + // It would be more correct to throw AUTO_RENEW_DURATION_NOT_IN_RANGE like the other services do, + // but this would break differential testing. So for now, we replicate the mono-service behaviour. + try { + validateAutoRenew(creationMeta); + } catch (HandleException e) { + if (e.getStatus() == AUTORENEW_DURATION_NOT_IN_RANGE) { + throw new HandleException(INVALID_RENEWAL_PERIOD); + } else { + throw e; + } } + context.attributeValidator().validateExpiry(effectiveExpiry); } else { // Even if the effective expiry is valid, we still also require any explicit auto-renew period to be valid - if (creationMeta.hasAutoRenewPeriod()) { - context.attributeValidator().validateAutoRenewPeriod(creationMeta.autoRenewPeriod()); - } + validateAutoRenew(creationMeta); context.attributeValidator().validateExpiry(effectiveExpiry); } return new ExpiryMeta(effectiveExpiry, creationMeta.autoRenewPeriod(), creationMeta.autoRenewAccountId()); } + private void validateAutoRenew(final ExpiryMeta creationMeta) { + if (creationMeta.hasAutoRenewPeriod()) { + context.attributeValidator().validateAutoRenewPeriod(creationMeta.autoRenewPeriod()); + } + } + /** * {@inheritDoc} */ @NonNull @Override public ExpiryMeta resolveUpdateAttempt( - @NonNull final ExpiryMeta currentMeta, @NonNull final ExpiryMeta updateMeta) { + @NonNull final ExpiryMeta currentMeta, + @NonNull final ExpiryMeta updateMeta, + final boolean isForTokenUpdate) { if (updateMeta.hasAutoRenewAccountId()) { validateAutoRenewAccount(updateMeta.autoRenewAccountId()); } @@ -114,8 +136,21 @@ public ExpiryMeta resolveUpdateAttempt( var resolvedAutoRenewPeriod = currentMeta.autoRenewPeriod(); if (updateMeta.hasAutoRenewPeriod()) { - context.attributeValidator().validateAutoRenewPeriod(updateMeta.autoRenewPeriod()); - resolvedAutoRenewPeriod = updateMeta.autoRenewPeriod(); + try { + context.attributeValidator().validateAutoRenewPeriod(updateMeta.autoRenewPeriod()); + resolvedAutoRenewPeriod = updateMeta.autoRenewPeriod(); + } catch (HandleException e) { + // In mono-service, INVALID_RENEWAL_PERIOD is thrown for token creation and update + // if the autoRenewPeriod is not in range. + // It would be more correct to throw AUTO_RENEW_DURATION_NOT_IN_RANGE like the other services do, + // but this would break differential testing. So for now, we replicate the mono-service behaviour. + // FUTURE: This condition should be removed after differential testing is done + if (isForTokenUpdate && e.getStatus() == AUTORENEW_DURATION_NOT_IN_RANGE) { + throw new HandleException(INVALID_RENEWAL_PERIOD); + } else { + throw e; + } + } } var resolvedAutoRenewAccountId = currentMeta.autoRenewAccountId(); diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/StandardizedExpiryValidator.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/StandardizedExpiryValidator.java index d00109d6ff28..7414e9788869 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/StandardizedExpiryValidator.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/workflows/handle/validation/StandardizedExpiryValidator.java @@ -17,14 +17,17 @@ package com.hedera.node.app.workflows.handle.validation; import static com.hedera.hapi.node.base.ResponseCodeEnum.ACCOUNT_EXPIRED_AND_PENDING_REMOVAL; +import static com.hedera.hapi.node.base.ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE; import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_EXPIRED_AND_PENDING_REMOVAL; import static com.hedera.hapi.node.base.ResponseCodeEnum.EXPIRATION_REDUCTION_NOT_ALLOWED; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_RENEWAL_PERIOD; import static com.hedera.hapi.node.base.ResponseCodeEnum.OK; import static com.hedera.node.app.spi.workflows.HandleException.validateFalse; import static com.hedera.node.app.spi.workflows.HandleException.validateTrue; import com.hedera.hapi.node.base.AccountID; +import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.base.ResponseCodeEnum; import com.hedera.node.app.service.mono.config.HederaNumbers; import com.hedera.node.app.service.mono.store.models.Id; @@ -78,7 +81,7 @@ public StandardizedExpiryValidator( public ExpiryMeta resolveCreationAttempt( final boolean entityCanSelfFundRenewal, @NonNull final ExpiryMeta creationMeta, - final boolean isForTopicCreate) { + @NonNull final HederaFunctionality functionality) { if (creationMeta.hasAutoRenewAccountId()) { validateAutoRenewAccount(creationMeta.autoRenewAccountId()); } @@ -94,13 +97,30 @@ public ExpiryMeta resolveCreationAttempt( // In mono-service this check is done first for topic creation. // To maintain same behaviour for differential testing this condition is needed. // FUTURE: This condition should be removed after differential testing is done - if (isForTopicCreate) { + if (functionality == HederaFunctionality.CONSENSUS_CREATE_TOPIC) { attributeValidator.validateExpiry(effectiveExpiry); // Even if the effective expiry is valid, we still also require any explicit auto-renew period to be valid if (creationMeta.hasAutoRenewPeriod()) { attributeValidator.validateAutoRenewPeriod(creationMeta.autoRenewPeriod()); } + } else if (functionality == HederaFunctionality.TOKEN_CREATE) { + // In mono-service, INVALID_RENEWAL_PERIOD is thrown for token creation and update + // if the autoRenewPeriod is not in range. + // It would be more correct to throw AUTO_RENEW_DURATION_NOT_IN_RANGE like the other services do, + // but this would break differential testing. So for now, we replicate the mono-service behaviour. + try { + if (creationMeta.hasAutoRenewPeriod()) { + attributeValidator.validateAutoRenewPeriod(creationMeta.autoRenewPeriod()); + } + } catch (HandleException e) { + if (e.getStatus() == AUTORENEW_DURATION_NOT_IN_RANGE) { + throw new HandleException(INVALID_RENEWAL_PERIOD); + } else { + throw e; + } + } + attributeValidator.validateExpiry(effectiveExpiry); } else { // Even if the effective expiry is valid, we still also require any explicit auto-renew period to be valid if (creationMeta.hasAutoRenewPeriod()) { @@ -117,7 +137,9 @@ public ExpiryMeta resolveCreationAttempt( @NonNull @Override public ExpiryMeta resolveUpdateAttempt( - @NonNull final ExpiryMeta currentMeta, @NonNull final ExpiryMeta updateMeta) { + @NonNull final ExpiryMeta currentMeta, + @NonNull final ExpiryMeta updateMeta, + final boolean isForTokenUpdate) { if (updateMeta.hasAutoRenewAccountId()) { validateAutoRenewAccount(updateMeta.autoRenewAccountId()); } @@ -131,8 +153,21 @@ public ExpiryMeta resolveUpdateAttempt( var resolvedAutoRenewPeriod = currentMeta.autoRenewPeriod(); if (updateMeta.hasAutoRenewPeriod()) { - attributeValidator.validateAutoRenewPeriod(updateMeta.autoRenewPeriod()); - resolvedAutoRenewPeriod = updateMeta.autoRenewPeriod(); + try { + attributeValidator.validateAutoRenewPeriod(updateMeta.autoRenewPeriod()); + resolvedAutoRenewPeriod = updateMeta.autoRenewPeriod(); + } catch (HandleException e) { + // In mono-service, INVALID_RENEWAL_PERIOD is thrown for token creation and update + // if the autoRenewPeriod is not in range. + // It would be more correct to throw AUTO_RENEW_DURATION_NOT_IN_RANGE like the other services do, + // but this would break differential testing. So for now, we replicate the mono-service behaviour. + // FUTURE: This condition should be removed after differential testing is done + if (isForTokenUpdate && e.getStatus() == AUTORENEW_DURATION_NOT_IN_RANGE) { + throw new HandleException(INVALID_RENEWAL_PERIOD); + } else { + throw e; + } + } } var resolvedAutoRenewId = currentMeta.autoRenewAccountId(); diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImplTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImplTest.java index 9de4012954e6..950578526556 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImplTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/AttributeValidatorImplTest.java @@ -16,9 +16,9 @@ package com.hedera.node.app.workflows.handle.validation; +import static com.hedera.hapi.node.base.ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE; import static com.hedera.hapi.node.base.ResponseCodeEnum.BAD_ENCODING; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_EXPIRATION_TIME; -import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_RENEWAL_PERIOD; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ZERO_BYTE_IN_STRING; import static com.hedera.hapi.node.base.ResponseCodeEnum.MEMO_TOO_LONG; import static com.hedera.node.app.spi.fixtures.workflows.ExceptionConditions.responseCode; @@ -117,7 +117,7 @@ void rejectsBriefAutoRenewPeriod() { assertThatThrownBy(() -> subject.validateAutoRenewPeriod(55L)) .isInstanceOf(HandleException.class) - .has(responseCode(INVALID_RENEWAL_PERIOD)); + .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); } @Test @@ -130,7 +130,7 @@ void rejectsOverLongAutoRenewPeriod() { assertThatThrownBy(() -> subject.validateAutoRenewPeriod(10_001L)) .isInstanceOf(HandleException.class) - .has(responseCode(INVALID_RENEWAL_PERIOD)); + .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); } @Test diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImplTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImplTest.java index 7ce703d70e47..827e0f1e7b8f 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImplTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/ExpiryValidatorImplTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mock.Strictness.LENIENT; import com.hedera.hapi.node.base.AccountID; +import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.state.token.Account; import com.hedera.node.app.service.evm.exceptions.InvalidTransactionException; import com.hedera.node.app.service.token.ReadableAccountStore; @@ -90,11 +91,11 @@ void onCreationRequiresEitherExplicitValueOrFullAutoRenewMetaIfNotSelfFunding() .given(attributeValidator) .validateExpiry(anyLong()); final var expiryMeta1 = new ExpiryMeta(NA, NA, AN_AUTO_RENEW_ID); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta1, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta1, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_EXPIRATION_TIME)); final var expiryMeta2 = new ExpiryMeta(NA, A_PERIOD, null); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta2, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta2, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_EXPIRATION_TIME)); } @@ -109,7 +110,7 @@ void validatesShard() { A_PERIOD, AccountID.newBuilder().shardNum(2L).realmNum(2L).accountNum(888).build()); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, newMeta, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, newMeta, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_AUTORENEW_ACCOUNT)); } @@ -126,7 +127,7 @@ void validatesRealm() { A_PERIOD, AccountID.newBuilder().shardNum(1L).realmNum(3L).accountNum(888).build()); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, newMeta, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, newMeta, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_AUTORENEW_ACCOUNT)); } @@ -138,7 +139,7 @@ void onCreationRequiresValidExpiryIfExplicit() { .validateExpiry(A_TIME); final var expiryMeta = new ExpiryMeta(A_TIME, NA, AN_AUTO_RENEW_ID); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_EXPIRATION_TIME)); } @@ -150,14 +151,15 @@ void translatesFailureOnExplicitAutoRenewAccount() { com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT)); final var expiryMeta = new ExpiryMeta(A_TIME, NA, AN_AUTO_RENEW_ID); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_AUTORENEW_ACCOUNT)); } @Test void onCreationUsesAutoRenewPeriodEvenWithoutFullSpecIfSelfFunding() { - assertThatCode(() -> subject.resolveCreationAttempt(true, new ExpiryMeta(NA, A_PERIOD, null), false)) + assertThatCode(() -> subject.resolveCreationAttempt( + true, new ExpiryMeta(NA, A_PERIOD, null), HederaFunctionality.NONE)) .doesNotThrowAnyException(); } @@ -168,7 +170,7 @@ void onCreationRequiresValidExpiryIfImplicit() { .validateExpiry(NOW.getEpochSecond() + A_PERIOD); final var expiryMeta = new ExpiryMeta(NA, A_PERIOD, AN_AUTO_RENEW_ID); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_EXPIRATION_TIME)); } @@ -180,7 +182,7 @@ void validatesAutoRenewPeriodIfSet() { .validateAutoRenewPeriod(A_PERIOD); final var expiryMeta = new ExpiryMeta(A_TIME, A_PERIOD, null); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); } @@ -192,33 +194,38 @@ void validatesImpliedExpiry() { .validateAutoRenewPeriod(A_PERIOD); final var expiryMeta = new ExpiryMeta(A_TIME, A_PERIOD, null); - assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, false)) + assertThatThrownBy(() -> subject.resolveCreationAttempt(false, expiryMeta, HederaFunctionality.NONE)) .isInstanceOf(HandleException.class) .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); } @Test void summarizesExpiryOnlyCase() { - assertThatCode(() -> subject.resolveCreationAttempt(false, new ExpiryMeta(A_TIME, NA, null), false)) + assertThatCode(() -> subject.resolveCreationAttempt( + false, new ExpiryMeta(A_TIME, NA, null), HederaFunctionality.NONE)) .doesNotThrowAnyException(); } @Test void summarizesExpiryAndAutoRenewNumCase() { - assertThatCode(() -> subject.resolveCreationAttempt(false, new ExpiryMeta(A_TIME, NA, AN_AUTO_RENEW_ID), false)) + assertThatCode(() -> subject.resolveCreationAttempt( + false, new ExpiryMeta(A_TIME, NA, AN_AUTO_RENEW_ID), HederaFunctionality.NONE)) .doesNotThrowAnyException(); } @Test void summarizesExpiryAndValidAutoRenewPeriodCase() { - assertThatCode(() -> subject.resolveCreationAttempt(false, new ExpiryMeta(A_TIME, A_PERIOD, null), false)) + assertThatCode(() -> subject.resolveCreationAttempt( + false, new ExpiryMeta(A_TIME, A_PERIOD, null), HederaFunctionality.NONE)) .doesNotThrowAnyException(); } @Test void summarizesFullAutoRenewSpecPeriodCase() { assertThatCode(() -> subject.resolveCreationAttempt( - false, new ExpiryMeta(NOW.getEpochSecond() + A_PERIOD, A_PERIOD, AN_AUTO_RENEW_ID), false)) + false, + new ExpiryMeta(NOW.getEpochSecond() + A_PERIOD, A_PERIOD, AN_AUTO_RENEW_ID), + HederaFunctionality.NONE)) .doesNotThrowAnyException(); } @@ -227,7 +234,7 @@ void updateCannotExplicitlyReduceExpiry() { final var current = new ExpiryMeta(A_TIME, NA, null); final var update = new ExpiryMeta(A_TIME - 1, NA, null); - assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update)) + assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update, false)) .isInstanceOf(HandleException.class) .has(responseCode(EXPIRATION_REDUCTION_NOT_ALLOWED)); } @@ -237,7 +244,7 @@ void explicitExpiryExtensionMustBeValid() { final var current = new ExpiryMeta(A_TIME, NA, null); final var update = new ExpiryMeta(A_TIME - 1, NA, null); - assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update)) + assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update, false)) .isInstanceOf(HandleException.class) .has(responseCode(EXPIRATION_REDUCTION_NOT_ALLOWED)); } @@ -251,7 +258,7 @@ void ifJustSettingAutoRenewAccountThenNetPeriodMustBeValid() { .given(attributeValidator) .validateAutoRenewPeriod(0L); - assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update)) + assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update, false)) .isInstanceOf(HandleException.class) .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); } @@ -265,7 +272,7 @@ void ifSettingAutoRenewPeriodThenMustBeValid() { .given(attributeValidator) .validateAutoRenewPeriod(B_PERIOD); - assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update)) + assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update, false)) .isInstanceOf(HandleException.class) .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); } @@ -279,7 +286,7 @@ void ifUpdatingAutoRenewNumMustBeValid() { .willThrow(new InvalidTransactionException( com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT)); - assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update)) + assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update, false)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_AUTORENEW_ACCOUNT)); } @@ -293,7 +300,7 @@ void ifUpdatingExpiryMustBeValid() { .given(attributeValidator) .validateExpiry(B_TIME); - assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update)) + assertThatThrownBy(() -> subject.resolveUpdateAttempt(current, update, false)) .isInstanceOf(HandleException.class) .has(responseCode(INVALID_EXPIRATION_TIME)); } @@ -303,7 +310,7 @@ void canSetEverythingValidly() { final var current = new ExpiryMeta(A_TIME, 0, null); final var update = new ExpiryMeta(B_TIME, B_PERIOD, AN_AUTO_RENEW_ID); - assertThat(subject.resolveUpdateAttempt(current, update)).isEqualTo(update); + assertThat(subject.resolveUpdateAttempt(current, update, false)).isEqualTo(update); } @Test @@ -314,7 +321,7 @@ void canUseWildcardForRemovingAutoRenewAccount() { B_PERIOD, AccountID.newBuilder().shardNum(0L).realmNum(0L).accountNum(0L).build()); - assertThat(subject.resolveUpdateAttempt(current, update)).isEqualTo(update); + assertThat(subject.resolveUpdateAttempt(current, update, false)).isEqualTo(update); } @Test diff --git a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/MonoExpiryValidatorTest.java b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/MonoExpiryValidatorTest.java index f01bbed9dac4..3928bc2d3ba1 100644 --- a/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/MonoExpiryValidatorTest.java +++ b/hedera-node/hedera-app/src/test/java/com/hedera/node/app/workflows/handle/validation/MonoExpiryValidatorTest.java @@ -31,6 +31,7 @@ import static org.mockito.BDDMockito.willThrow; import com.hedera.hapi.node.base.AccountID; +import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.base.ResponseCodeEnum; import com.hedera.node.app.service.evm.exceptions.InvalidTransactionException; import com.hedera.node.app.service.mono.config.HederaNumbers; @@ -97,10 +98,12 @@ void onCreationRequiresEitherExplicitValueOrFullAutoRenewMetaIfNotSelfFunding() .validateExpiry(anyLong()); assertFailsWith( ResponseCodeEnum.INVALID_EXPIRATION_TIME, - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(NA, NA, anAutoRenewId), false)); + () -> subject.resolveCreationAttempt( + false, new ExpiryMeta(NA, NA, anAutoRenewId), HederaFunctionality.NONE)); assertFailsWith( ResponseCodeEnum.INVALID_EXPIRATION_TIME, - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(NA, aPeriod, null), false)); + () -> subject.resolveCreationAttempt( + false, new ExpiryMeta(NA, aPeriod, null), HederaFunctionality.NONE)); } @Test @@ -111,8 +114,8 @@ void validatesShard() { aPeriod, AccountID.newBuilder().shardNum(2L).realmNum(2L).accountNum(888).build()); - final var failure = - assertThrows(HandleException.class, () -> subject.resolveCreationAttempt(false, newMeta, false)); + final var failure = assertThrows( + HandleException.class, () -> subject.resolveCreationAttempt(false, newMeta, HederaFunctionality.NONE)); assertEquals(ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT, failure.getStatus()); } @@ -125,8 +128,8 @@ void validatesRealm() { aPeriod, AccountID.newBuilder().shardNum(1L).realmNum(3L).accountNum(888).build()); - final var failure = - assertThrows(HandleException.class, () -> subject.resolveCreationAttempt(false, newMeta, false)); + final var failure = assertThrows( + HandleException.class, () -> subject.resolveCreationAttempt(false, newMeta, HederaFunctionality.NONE)); assertEquals(ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT, failure.getStatus()); } @@ -139,7 +142,8 @@ void onCreationRequiresValidExpiryIfExplicit() { .validateExpiry(aTime); assertFailsWith( ResponseCodeEnum.INVALID_EXPIRATION_TIME, - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, NA, anAutoRenewId), false)); + () -> subject.resolveCreationAttempt( + false, new ExpiryMeta(aTime, NA, anAutoRenewId), HederaFunctionality.NONE)); } @Test @@ -149,14 +153,16 @@ void translatesFailureOnExplicitAutoRenewAccount() { assertFailsWith( ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT, - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, aPeriod, anAutoRenewId), false)); + () -> subject.resolveCreationAttempt( + false, new ExpiryMeta(aTime, aPeriod, anAutoRenewId), HederaFunctionality.NONE)); } @Test void onCreationUsesAutoRenewPeriodEvenWithoutFullSpecIfSelfFunding() { given(consensusSecondNow.getAsLong()).willReturn(now); - assertDoesNotThrow(() -> subject.resolveCreationAttempt(true, new ExpiryMeta(NA, aPeriod, null), false)); + assertDoesNotThrow(() -> + subject.resolveCreationAttempt(true, new ExpiryMeta(NA, aPeriod, null), HederaFunctionality.NONE)); } @Test @@ -168,7 +174,8 @@ void onCreationRequiresValidExpiryIfImplicit() { .validateExpiry(now + aPeriod); assertFailsWith( ResponseCodeEnum.INVALID_EXPIRATION_TIME, - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(NA, aPeriod, anAutoRenewId), false)); + () -> subject.resolveCreationAttempt( + false, new ExpiryMeta(NA, aPeriod, anAutoRenewId), HederaFunctionality.NONE)); } @Test @@ -180,7 +187,8 @@ void validatesAutoRenewPeriodIfSet() { .validateAutoRenewPeriod(aPeriod); assertFailsWith( ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE, - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, aPeriod, null), false)); + () -> subject.resolveCreationAttempt( + false, new ExpiryMeta(aTime, aPeriod, null), HederaFunctionality.NONE)); } @Test @@ -191,37 +199,40 @@ void validatesImpliedExpiry() { .validateAutoRenewPeriod(aPeriod); assertFailsWith( ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE, - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, aPeriod, null), false)); + () -> subject.resolveCreationAttempt( + false, new ExpiryMeta(aTime, aPeriod, null), HederaFunctionality.NONE)); } @Test void summarizesExpiryOnlyCase() { given(consensusSecondNow.getAsLong()).willReturn(now); - assertDoesNotThrow(() -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, NA, null), false)); + assertDoesNotThrow( + () -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, NA, null), HederaFunctionality.NONE)); } @Test void summarizesExpiryAndAutoRenewNumCase() { given(consensusSecondNow.getAsLong()).willReturn(now); - assertDoesNotThrow( - () -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, NA, anAutoRenewId), false)); + assertDoesNotThrow(() -> subject.resolveCreationAttempt( + false, new ExpiryMeta(aTime, NA, anAutoRenewId), HederaFunctionality.NONE)); } @Test void summarizesExpiryAndValidAutoRenewPeriodCase() { given(consensusSecondNow.getAsLong()).willReturn(now); - assertDoesNotThrow(() -> subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, aPeriod, null), false)); + assertDoesNotThrow(() -> + subject.resolveCreationAttempt(false, new ExpiryMeta(aTime, aPeriod, null), HederaFunctionality.NONE)); } @Test void summarizesFullAutoRenewSpecPeriodCase() { given(consensusSecondNow.getAsLong()).willReturn(now); - assertDoesNotThrow(() -> - subject.resolveCreationAttempt(false, new ExpiryMeta(now + aPeriod, aPeriod, anAutoRenewId), false)); + assertDoesNotThrow(() -> subject.resolveCreationAttempt( + false, new ExpiryMeta(now + aPeriod, aPeriod, anAutoRenewId), HederaFunctionality.NONE)); } @Test @@ -230,7 +241,8 @@ void updateCannotExplicitlyReduceExpiry() { final var update = new ExpiryMeta(aTime - 1, NA, null); assertFailsWith( - ResponseCodeEnum.EXPIRATION_REDUCTION_NOT_ALLOWED, () -> subject.resolveUpdateAttempt(current, update)); + ResponseCodeEnum.EXPIRATION_REDUCTION_NOT_ALLOWED, + () -> subject.resolveUpdateAttempt(current, update, false)); } @Test @@ -239,7 +251,8 @@ void explicitExpiryExtensionMustBeValid() { final var update = new ExpiryMeta(aTime - 1, NA, null); assertFailsWith( - ResponseCodeEnum.EXPIRATION_REDUCTION_NOT_ALLOWED, () -> subject.resolveUpdateAttempt(current, update)); + ResponseCodeEnum.EXPIRATION_REDUCTION_NOT_ALLOWED, + () -> subject.resolveUpdateAttempt(current, update, false)); } @Test @@ -252,7 +265,8 @@ void ifJustSettingAutoRenewAccountThenNetPeriodMustBeValid() { .validateAutoRenewPeriod(0L); assertFailsWith( - ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE, () -> subject.resolveUpdateAttempt(current, update)); + ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE, + () -> subject.resolveUpdateAttempt(current, update, false)); } @Test @@ -265,7 +279,8 @@ void ifSettingAutoRenewPeriodThenMustBeValid() { .validateAutoRenewPeriod(bPeriod); assertFailsWith( - ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE, () -> subject.resolveUpdateAttempt(current, update)); + ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE, + () -> subject.resolveUpdateAttempt(current, update, false)); } @Test @@ -277,7 +292,7 @@ void ifUpdatingAutoRenewNumMustBeValid() { .willThrow(new InvalidTransactionException(INVALID_AUTORENEW_ACCOUNT)); assertFailsWith( - ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT, () -> subject.resolveUpdateAttempt(current, update)); + ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT, () -> subject.resolveUpdateAttempt(current, update, false)); } @Test @@ -289,7 +304,8 @@ void ifUpdatingExpiryMustBeValid() { .given(attributeValidator) .validateExpiry(bTime); - assertFailsWith(ResponseCodeEnum.INVALID_EXPIRATION_TIME, () -> subject.resolveUpdateAttempt(current, update)); + assertFailsWith( + ResponseCodeEnum.INVALID_EXPIRATION_TIME, () -> subject.resolveUpdateAttempt(current, update, false)); } @Test @@ -297,7 +313,7 @@ void canSetEverythingValidly() { final var current = new ExpiryMeta(aTime, 0, null); final var update = new ExpiryMeta(bTime, bPeriod, anAutoRenewId); - assertEquals(update, subject.resolveUpdateAttempt(current, update)); + assertEquals(update, subject.resolveUpdateAttempt(current, update, false)); } @Test @@ -306,7 +322,7 @@ void canUseWildcardForRemovingAutoRenewAccount() { final var update = new ExpiryMeta( bTime, bPeriod, AccountID.newBuilder().accountNum(0).build()); - assertEquals(update, subject.resolveUpdateAttempt(current, update)); + assertEquals(update, subject.resolveUpdateAttempt(current, update, false)); } @Test diff --git a/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusCreateTopicHandler.java b/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusCreateTopicHandler.java index 739b000fa6aa..cfb67eb4e97c 100644 --- a/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusCreateTopicHandler.java +++ b/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusCreateTopicHandler.java @@ -122,8 +122,9 @@ public void handle(@NonNull final HandleContext handleContext) { impliedExpiry, op.autoRenewPeriodOrElse(Duration.DEFAULT).seconds(), op.autoRenewAccount()); try { - final var effectiveExpiryMeta = - handleContext.expiryValidator().resolveCreationAttempt(false, entityExpiryMeta, true); + final var effectiveExpiryMeta = handleContext + .expiryValidator() + .resolveCreationAttempt(false, entityExpiryMeta, HederaFunctionality.CONSENSUS_CREATE_TOPIC); builder.autoRenewPeriod(effectiveExpiryMeta.autoRenewPeriod()); builder.expirationSecond(effectiveExpiryMeta.expiry()); builder.autoRenewAccountId(effectiveExpiryMeta.autoRenewAccountId()); diff --git a/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusUpdateTopicHandler.java b/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusUpdateTopicHandler.java index 038312fc89c1..3464ba73ce00 100644 --- a/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusUpdateTopicHandler.java +++ b/hedera-node/hedera-consensus-service-impl/src/main/java/com/hedera/node/app/service/consensus/impl/handlers/ConsensusUpdateTopicHandler.java @@ -223,7 +223,7 @@ private ExpiryMeta resolvedUpdateMetaFrom( if (updatesExpiryMeta(op)) { final var updateMeta = new ExpiryMeta(effExpiryOf(op), effAutoRenewPeriodOf(op), op.autoRenewAccount()); try { - return expiryValidator.resolveUpdateAttempt(currentMeta, updateMeta); + return expiryValidator.resolveUpdateAttempt(currentMeta, updateMeta, false); } catch (final HandleException e) { if (e.getStatus() == INVALID_RENEWAL_PERIOD) { // Tokens throw INVALID_EXPIRATION_TIME, but for topic it's expected currently to throw diff --git a/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusCreateTopicTest.java b/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusCreateTopicTest.java index 89b58e52f032..fbf5213aa729 100644 --- a/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusCreateTopicTest.java +++ b/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusCreateTopicTest.java @@ -258,7 +258,7 @@ void handleWorksAsExpected() { given(handleContext.consensusNow()).willReturn(Instant.ofEpochSecond(1_234_567L)); given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.expiryValidator()).willReturn(expiryValidator); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willReturn(new ExpiryMeta( 1_234_567L + op.autoRenewPeriod().seconds(), op.autoRenewPeriod().seconds(), @@ -294,7 +294,7 @@ void handleDoesntRequireKeys() { given(handleContext.consensusNow()).willReturn(Instant.ofEpochSecond(1_234_567L)); given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.expiryValidator()).willReturn(expiryValidator); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willReturn(new ExpiryMeta( 1_234_567L + op.autoRenewPeriod().seconds(), op.autoRenewPeriod().seconds(), @@ -329,7 +329,7 @@ void translatesInvalidExpiryException() { given(handleContext.consensusNow()).willReturn(Instant.ofEpochSecond(1_234_567L)); given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.expiryValidator()).willReturn(expiryValidator); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willThrow(new HandleException(ResponseCodeEnum.INVALID_EXPIRATION_TIME)); final var msg = assertThrows(HandleException.class, () -> subject.handle(handleContext)); @@ -345,7 +345,7 @@ void doesntTranslateInvalidAutoRenewNum() { given(handleContext.consensusNow()).willReturn(Instant.ofEpochSecond(1_234_567L)); given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.expiryValidator()).willReturn(expiryValidator); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willThrow(new HandleException(INVALID_AUTORENEW_ACCOUNT)); final var msg = assertThrows(HandleException.class, () -> subject.handle(handleContext)); @@ -430,7 +430,7 @@ void validatedAutoRenewAccount() { given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.expiryValidator()).willReturn(expiryValidator); - doThrow(HandleException.class).when(expiryValidator).resolveCreationAttempt(anyBoolean(), any(), anyBoolean()); + doThrow(HandleException.class).when(expiryValidator).resolveCreationAttempt(anyBoolean(), any(), any()); final var failure = assertThrows(HandleException.class, () -> subject.handle(handleContext)); assertEquals(0, topicStore.modifiedTopics().size()); diff --git a/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusUpdateTopicTest.java b/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusUpdateTopicTest.java index 3df2293c7d7f..3ccb51a8df55 100644 --- a/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusUpdateTopicTest.java +++ b/hedera-node/hedera-consensus-service-impl/src/test/java/com/hedera/node/app/service/consensus/impl/test/handlers/ConsensusUpdateTopicTest.java @@ -348,7 +348,7 @@ void validatesNewExpiryViaMeta() { final var impliedMeta = new ExpiryMeta(123L, NA, null); willThrow(new HandleException(ResponseCodeEnum.INVALID_EXPIRATION_TIME)) .given(expiryValidator) - .resolveUpdateAttempt(currentExpiryMeta, impliedMeta); + .resolveUpdateAttempt(currentExpiryMeta, impliedMeta, false); // expect: assertFailsWith(ResponseCodeEnum.INVALID_EXPIRATION_TIME, () -> subject.handle(handleContext)); @@ -366,7 +366,7 @@ void appliesNewExpiryViaMeta() { given(handleContext.expiryValidator()).willReturn(expiryValidator); given(handleContext.attributeValidator()).willReturn(attributeValidator); final var impliedMeta = new ExpiryMeta(123L, NA, null); - given(expiryValidator.resolveUpdateAttempt(currentExpiryMeta, impliedMeta)) + given(expiryValidator.resolveUpdateAttempt(currentExpiryMeta, impliedMeta, false)) .willReturn(new ExpiryMeta( 123L, currentExpiryMeta.autoRenewPeriod(), currentExpiryMeta.autoRenewAccountId())); @@ -391,7 +391,7 @@ void validatesNewAutoRenewPeriodViaMeta() { final var impliedMeta = new ExpiryMeta(NA, 123L, null); willThrow(new HandleException(ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE)) .given(expiryValidator) - .resolveUpdateAttempt(currentExpiryMeta, impliedMeta); + .resolveUpdateAttempt(currentExpiryMeta, impliedMeta, false); // expect: assertFailsWith(ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE, () -> subject.handle(handleContext)); @@ -409,7 +409,7 @@ void appliesNewAutoRenewPeriodViaMeta() { given(handleContext.attributeValidator()).willReturn(attributeValidator); given(handleContext.expiryValidator()).willReturn(expiryValidator); final var impliedMeta = new ExpiryMeta(NA, 123L, null); - given(expiryValidator.resolveUpdateAttempt(currentExpiryMeta, impliedMeta)) + given(expiryValidator.resolveUpdateAttempt(currentExpiryMeta, impliedMeta, false)) .willReturn(new ExpiryMeta(currentExpiryMeta.expiry(), 123L, null)); subject.handle(handleContext); @@ -431,7 +431,7 @@ void validatesNewAutoRenewAccountViaMeta() { final var impliedMeta = new ExpiryMeta(NA, NA, autoRenewId); willThrow(new HandleException(INVALID_AUTORENEW_ACCOUNT)) .given(expiryValidator) - .resolveUpdateAttempt(currentExpiryMeta, impliedMeta); + .resolveUpdateAttempt(currentExpiryMeta, impliedMeta, false); // expect: assertFailsWith(INVALID_AUTORENEW_ACCOUNT, () -> subject.handle(handleContext)); @@ -453,7 +453,7 @@ void appliesNewAutoRenewNumViaMeta() { NA, NA, AccountID.newBuilder().shardNum(0).realmNum(0).accountNum(666).build()); - given(expiryValidator.resolveUpdateAttempt(currentExpiryMeta, impliedMeta)) + given(expiryValidator.resolveUpdateAttempt(currentExpiryMeta, impliedMeta, false)) .willReturn(new ExpiryMeta( currentExpiryMeta.expiry(), currentExpiryMeta.autoRenewPeriod(), diff --git a/hedera-node/hedera-file-service-impl/src/main/java/com/hedera/node/app/service/file/impl/handlers/FileCreateHandler.java b/hedera-node/hedera-file-service-impl/src/main/java/com/hedera/node/app/service/file/impl/handlers/FileCreateHandler.java index 89eb54d5fe89..eeecec898dbc 100644 --- a/hedera-node/hedera-file-service-impl/src/main/java/com/hedera/node/app/service/file/impl/handlers/FileCreateHandler.java +++ b/hedera-node/hedera-file-service-impl/src/main/java/com/hedera/node/app/service/file/impl/handlers/FileCreateHandler.java @@ -112,8 +112,9 @@ public void handle(@NonNull final HandleContext handleContext) throws HandleExce null); try { - final var effectiveExpiryMeta = - handleContext.expiryValidator().resolveCreationAttempt(false, entityExpiryMeta, false); + final var effectiveExpiryMeta = handleContext + .expiryValidator() + .resolveCreationAttempt(false, entityExpiryMeta, HederaFunctionality.FILE_CREATE); builder.expirationSecond(effectiveExpiryMeta.expiry()); handleContext.attributeValidator().validateMemo(fileCreateTransactionBody.memo()); diff --git a/hedera-node/hedera-file-service-impl/src/test/java/com/hedera/node/app/service/file/impl/test/handlers/FileCreateTest.java b/hedera-node/hedera-file-service-impl/src/test/java/com/hedera/node/app/service/file/impl/test/handlers/FileCreateTest.java index 44942a20cc93..e7fb5ab4a092 100644 --- a/hedera-node/hedera-file-service-impl/src/test/java/com/hedera/node/app/service/file/impl/test/handlers/FileCreateTest.java +++ b/hedera-node/hedera-file-service-impl/src/test/java/com/hedera/node/app/service/file/impl/test/handlers/FileCreateTest.java @@ -204,7 +204,7 @@ void handleWorksAsExpected() { given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.writableStore(WritableFileStore.class)).willReturn(writableStore); given(handleContext.expiryValidator()).willReturn(expiryValidator); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willReturn(new ExpiryMeta(expirationTime, NA, null)); given(handleContext.newEntityNum()).willReturn(1_234L); given(handleContext.recordBuilder(CreateFileRecordBuilder.class)).willReturn(recordBuilder); @@ -235,7 +235,7 @@ void handleDoesntRequireKeys() { given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.writableStore(WritableFileStore.class)).willReturn(writableStore); given(handleContext.expiryValidator()).willReturn(expiryValidator); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willReturn(new ExpiryMeta(1_234_567L, NA, null)); given(handleContext.newEntityNum()).willReturn(1_234L); given(handleContext.recordBuilder(CreateFileRecordBuilder.class)).willReturn(recordBuilder); @@ -265,7 +265,7 @@ void translatesInvalidExpiryException() { given(handleContext.body()).willReturn(txBody); given(handleContext.expiryValidator()).willReturn(expiryValidator); given(handleContext.writableStore(WritableFileStore.class)).willReturn(writableStore); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willThrow(new HandleException(ResponseCodeEnum.INVALID_EXPIRATION_TIME)); final var failure = assertThrows(HandleException.class, () -> subject.handle(handleContext)); @@ -282,7 +282,7 @@ void handleThrowsIfAttributeValidatorFails() { given(handleContext.attributeValidator()).willReturn(validator); given(handleContext.writableStore(WritableFileStore.class)).willReturn(writableStore); given(handleContext.expiryValidator()).willReturn(expiryValidator); - given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), anyBoolean())) + given(expiryValidator.resolveCreationAttempt(anyBoolean(), any(), any())) .willReturn(new ExpiryMeta(1_234_567L, NA, null)); doThrow(new HandleException(ResponseCodeEnum.MEMO_TOO_LONG)) diff --git a/hedera-node/hedera-network-admin-service-impl/src/main/java/com/hedera/node/app/service/networkadmin/impl/handlers/NetworkUncheckedSubmitHandler.java b/hedera-node/hedera-network-admin-service-impl/src/main/java/com/hedera/node/app/service/networkadmin/impl/handlers/NetworkUncheckedSubmitHandler.java index 8311286c8fee..8d0410212587 100644 --- a/hedera-node/hedera-network-admin-service-impl/src/main/java/com/hedera/node/app/service/networkadmin/impl/handlers/NetworkUncheckedSubmitHandler.java +++ b/hedera-node/hedera-network-admin-service-impl/src/main/java/com/hedera/node/app/service/networkadmin/impl/handlers/NetworkUncheckedSubmitHandler.java @@ -34,8 +34,11 @@ /** * This class contains all workflow-related functionality regarding {@link HederaFunctionality#UNCHECKED_SUBMIT}. *

- * This transaction type has been deprecated. Because protobufs promise backwards compatibility, - * we cannot remove it. However, it should not be used. + * Unchecked submit is a mechanism to bypass ingest checks. This is a dangerous operation and will be removed + * in the future. + * Transactions that are wrapped in an unchecked submit call are unwrapped during ingest and then submitted directly. + * Therefore, unchecked submit is not a transaction type that is actually submitted to the network and there is no + * reason to implement a handler for it. This class exists for completeness but should never actually be called. */ @Singleton public class NetworkUncheckedSubmitHandler implements TransactionHandler { diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/AbstractRevertibleTokenViewCall.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/AbstractRevertibleTokenViewCall.java index 20d4736a42b1..3c41da25bf63 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/AbstractRevertibleTokenViewCall.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/AbstractRevertibleTokenViewCall.java @@ -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.HederaSystemContract.FullResult.revertResult; 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; @@ -64,7 +65,8 @@ protected AbstractRevertibleTokenViewCall( .systemOperations() .externalizeResult( contractFunctionResultSuccessFor(gasRequirement, output, contractID), - SystemContractUtils.ResultStatus.IS_SUCCESS); + SystemContractUtils.ResultStatus.IS_SUCCESS, + SUCCESS); return result; } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractUpdateHandler.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractUpdateHandler.java index 23a5c06b469c..9aa0fbb90cfb 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractUpdateHandler.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/handlers/ContractUpdateHandler.java @@ -198,7 +198,7 @@ private void validateSemantics(Account contract, HandleContext context, Contract op.hasExpirationTime() ? op.expirationTime().seconds() : NA, op.hasAutoRenewPeriod() ? op.autoRenewPeriod().seconds() : NA, null); - context.expiryValidator().resolveUpdateAttempt(currentMetadata, updateMeta); + context.expiryValidator().resolveUpdateAttempt(currentMetadata, updateMeta, false); } boolean onlyAffectsExpiry(ContractUpdateTransactionBody op) { diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/infra/HevmTransactionFactory.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/infra/HevmTransactionFactory.java index 94bb0244b031..5e18f8e7cf76 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/infra/HevmTransactionFactory.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/infra/HevmTransactionFactory.java @@ -47,6 +47,7 @@ import com.hedera.hapi.node.base.ContractID; import com.hedera.hapi.node.base.Duration; import com.hedera.hapi.node.base.FileID; +import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.base.Key; import com.hedera.hapi.node.contract.ContractCallTransactionBody; import com.hedera.hapi.node.contract.ContractCreateTransactionBody; @@ -289,7 +290,7 @@ private void assertValidCreation(@NonNull final ContractCreateTransactionBody bo true, new ExpiryMeta( NA, autoRenewPeriod, body.hasAutoRenewAccountId() ? body.autoRenewAccountIdOrThrow() : null), - false); + HederaFunctionality.CONTRACT_CREATE); } private Bytes initcodeFor(@NonNull final ContractCreateTransactionBody body) { diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/infra/HevmTransactionFactoryTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/infra/HevmTransactionFactoryTest.java index 0ccdb4809110..8499812a1523 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/infra/HevmTransactionFactoryTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/infra/HevmTransactionFactoryTest.java @@ -76,6 +76,7 @@ import com.hedera.hapi.node.base.ContractID; import com.hedera.hapi.node.base.Duration; import com.hedera.hapi.node.base.FileID; +import com.hedera.hapi.node.base.HederaFunctionality; import com.hedera.hapi.node.base.Key; import com.hedera.hapi.node.base.KeyList; import com.hedera.hapi.node.base.ResponseCodeEnum; @@ -319,7 +320,7 @@ void fromHapiCreationValidatesAutoRenewId() { final var createMeta = new ExpiryMeta(NA, SOME_DURATION.seconds(), NON_SYSTEM_ACCOUNT_ID); doThrow(new HandleException(INVALID_AUTORENEW_ACCOUNT)) .when(expiryValidator) - .resolveCreationAttempt(true, createMeta, false); + .resolveCreationAttempt(true, createMeta, HederaFunctionality.CONTRACT_CREATE); assertCreateFailsWith(INVALID_AUTORENEW_ACCOUNT, b -> b.memo(SOME_MEMO) .adminKey(AN_ED25519_KEY) .autoRenewAccountId(NON_SYSTEM_ACCOUNT_ID) diff --git a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/CryptoUpdateHandler.java b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/CryptoUpdateHandler.java index df830dc8881e..40104aeadb26 100644 --- a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/CryptoUpdateHandler.java +++ b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/CryptoUpdateHandler.java @@ -246,7 +246,7 @@ private void validateSemantics( op.hasExpirationTime() ? op.expirationTime().seconds() : NA, op.hasAutoRenewPeriod() ? op.autoRenewPeriod().seconds() : NA, null); - context.expiryValidator().resolveUpdateAttempt(currentMetadata, updateMeta); + context.expiryValidator().resolveUpdateAttempt(currentMetadata, updateMeta, false); // If an account is detached and pending removal, it cannot be updated // It can only be updated to extend expiration time diff --git a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/TokenCreateHandler.java b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/TokenCreateHandler.java index bc3110e1c295..84f4f6cb15f8 100644 --- a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/TokenCreateHandler.java +++ b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/TokenCreateHandler.java @@ -327,7 +327,8 @@ private ExpiryMeta validateSemantics( // validate expiration and auto-renew account if present final var givenExpiryMeta = getExpiryMeta(op); - final var resolvedExpiryMeta = context.expiryValidator().resolveCreationAttempt(false, givenExpiryMeta, false); + final var resolvedExpiryMeta = context.expiryValidator() + .resolveCreationAttempt(false, givenExpiryMeta, HederaFunctionality.TOKEN_CREATE); // validate auto-renew account exists if (resolvedExpiryMeta.hasAutoRenewAccountId()) { diff --git a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/validators/TokenUpdateValidator.java b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/validators/TokenUpdateValidator.java index 4475a7a23037..c07e76ecda20 100644 --- a/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/validators/TokenUpdateValidator.java +++ b/hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/validators/TokenUpdateValidator.java @@ -122,6 +122,6 @@ private ExpiryMeta resolveExpiry( op.hasExpiry() ? op.expiryOrThrow().seconds() : NA, op.hasAutoRenewPeriod() ? op.autoRenewPeriodOrThrow().seconds() : NA, op.autoRenewAccount()); - return expiryValidator.resolveUpdateAttempt(givenExpiryMeta, updateExpiryMeta); + return expiryValidator.resolveUpdateAttempt(givenExpiryMeta, updateExpiryMeta, true); } } diff --git a/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/TokenCreateHandlerTest.java b/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/TokenCreateHandlerTest.java index e6d8fcb6dd9a..c58c81b9dad1 100644 --- a/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/TokenCreateHandlerTest.java +++ b/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/TokenCreateHandlerTest.java @@ -16,13 +16,13 @@ package com.hedera.node.app.service.token.impl.test.handlers; -import static com.hedera.hapi.node.base.ResponseCodeEnum.AUTORENEW_DURATION_NOT_IN_RANGE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ADMIN_KEY; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_AUTORENEW_ACCOUNT; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_CUSTOM_FEE_SCHEDULE_KEY; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_EXPIRATION_TIME; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_FREEZE_KEY; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_KYC_KEY; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_RENEWAL_PERIOD; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SUPPLY_KEY; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_DECIMALS; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_INITIAL_SUPPLY; @@ -706,13 +706,13 @@ void failsOnInvalidAutoRenewPeriod() { given(handleContext.body()).willReturn(txn); assertThatThrownBy(() -> subject.handle(handleContext)) .isInstanceOf(HandleException.class) - .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); + .has(responseCode(INVALID_RENEWAL_PERIOD)); txn = new TokenCreateBuilder().withAutoRenewPeriod(100).build(); given(handleContext.body()).willReturn(txn); assertThatThrownBy(() -> subject.handle(handleContext)) .isInstanceOf(HandleException.class) - .has(responseCode(AUTORENEW_DURATION_NOT_IN_RANGE)); + .has(responseCode(INVALID_RENEWAL_PERIOD)); } @Test diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java index 6951386b638d..bd6a4176ba18 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoCreateSuite.java @@ -64,7 +64,6 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.Disabled; @HapiTestSuite public class CryptoCreateSuite extends HapiSuite { @@ -263,7 +262,6 @@ private HapiSpec usdFeeAsExpected() { } @HapiTest - @Disabled("Failing or intermittently failing HAPI Test") public HapiSpec syntaxChecksAreAsExpected() { return defaultHapiSpec("SyntaxChecksAreAsExpected") .given() @@ -271,9 +269,6 @@ public HapiSpec syntaxChecksAreAsExpected() { .then( cryptoCreate("broken").autoRenewSecs(1L).hasPrecheck(AUTORENEW_DURATION_NOT_IN_RANGE), cryptoCreate("alsoBroken").entityMemo(ZERO_BYTE_MEMO).hasPrecheck(INVALID_ZERO_BYTE_IN_STRING)); - // In modular code this error is thrown in handle, but it is fixed using dynamic property - // spec.streamlinedIngestChecks - // to accommodate error codes moved from Ingest to handle } @HapiTest