Skip to content

Commit

Permalink
fix: conditional records of hollow account creation via internal tran…
Browse files Browse the repository at this point in the history
…sfer with `EthereumTransaction` (#10539)

Signed-off-by: Miroslav Gatsanoga <miroslav.gatsanoga@limechain.tech>
Signed-off-by: Michael Tinker <michael.tinker@swirldslabs.com>
Co-authored-by: Michael Tinker <michael.tinker@swirldslabs.com>
  • Loading branch information
MiroslavGatsanoga and tinker-michaelj committed Dec 24, 2023
1 parent 3c74658 commit c7dd6e6
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
import com.swirlds.platform.system.transaction.ConsensusTransaction;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.time.Instant;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
Expand All @@ -113,6 +114,10 @@
public class HandleWorkflow {

private static final Logger logger = LogManager.getLogger(HandleWorkflow.class);
private static final Set<HederaFunctionality> DISPATCHING_CONTRACT_TRANSACTIONS = EnumSet.of(
HederaFunctionality.CONTRACT_CREATE,
HederaFunctionality.CONTRACT_CALL,
HederaFunctionality.ETHEREUM_TRANSACTION);

private final NetworkInfo networkInfo;
private final PreHandleWorkflow preHandleWorkflow;
Expand Down Expand Up @@ -437,8 +442,14 @@ private void handleUserTransaction(

// Dispatch the transaction to the handler
dispatcher.dispatchHandle(context);
// Possibly charge assessed fees for preceding child transactions
if (!recordListBuilder.precedingRecordBuilders().isEmpty()) {
// Possibly charge assessed fees for preceding child transactions; but
// only if not a contract operation, since these dispatches were already
// charged using gas. [FUTURE - stop setting transactionFee in recordBuilder
// at the point of dispatch, so we no longer need this special case here.]
final var isContractOp =
DISPATCHING_CONTRACT_TRANSACTIONS.contains(transactionInfo.functionality());
if (!isContractOp
&& !recordListBuilder.precedingRecordBuilders().isEmpty()) {
// We intentionally charge fees even if the transaction failed (may need to update
// mono-service to this behavior?)
final var childFees = recordListBuilder.precedingRecordBuilders().stream()
Expand Down Expand Up @@ -685,8 +696,9 @@ private record ValidationResult(

/**
* Rolls back the stack and sets the status of the transaction in case of a failure.
*
* @param rollbackStack whether to rollback the stack. Will be false when the failure is due to a
* {@link HandleException} that is due to a contract call revert.
* {@link HandleException} that is due to a contract call revert.
* @param status the status to set
* @param stack the save point stack to rollback
* @param recordListBuilder the record list builder to revert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
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.ResponseCodeEnum;
import com.hedera.hapi.node.token.CryptoTransferTransactionBody;
import com.hedera.hapi.node.token.CryptoUpdateTransactionBody;
import com.hedera.hapi.node.transaction.TransactionBody;
import com.hedera.node.app.service.contract.impl.annotations.TransactionScope;
import com.hedera.node.app.service.token.ReadableAccountStore;
Expand All @@ -33,6 +35,7 @@
import com.hedera.node.app.service.token.ReadableTokenStore;
import com.hedera.node.app.service.token.api.TokenServiceApi;
import com.hedera.node.app.service.token.records.CryptoCreateRecordBuilder;
import com.hedera.node.app.spi.fees.Fees;
import com.hedera.node.app.spi.workflows.HandleContext;
import com.hedera.node.app.spi.workflows.HandleException;
import com.hedera.pbj.runtime.io.buffer.Bytes;
Expand Down Expand Up @@ -101,12 +104,18 @@ public void setNonce(final long contractNumber, final long nonce) {
final var synthTxn = TransactionBody.newBuilder()
.cryptoCreateAccount(synthHollowAccountCreation(evmAddress))
.build();

// Note the use of the null "verification assistant" callback; we don't want any
// signing requirements enforced for this synthetic transaction
try {
final var childRecordBuilder = context.dispatchRemovablePrecedingTransaction(
synthTxn, CryptoCreateRecordBuilder.class, null, context.payer());
childRecordBuilder.memo(LAZY_CREATION_MEMO);

final var lazyCreateFees = context.dispatchComputeFees(synthTxn, context.payer());
final var finalizationFees = getLazyCreationFinalizationFees();
childRecordBuilder.transactionFee(lazyCreateFees.totalFee() + finalizationFees.totalFee());

return childRecordBuilder.status();
} catch (final HandleException e) {
// It is critically important we don't let HandleExceptions propagate to the workflow because
Expand Down Expand Up @@ -166,4 +175,12 @@ public boolean checkForCustomFees(@NonNull final CryptoTransferTransactionBody o
final var tokenServiceApi = context.serviceApi(TokenServiceApi.class);
return tokenServiceApi.checkForCustomFees(op);
}

private Fees getLazyCreationFinalizationFees() {
final var updateTxnBody =
CryptoUpdateTransactionBody.newBuilder().key(Key.newBuilder().ecdsaSecp256k1(Bytes.EMPTY));
final var synthTxn =
TransactionBody.newBuilder().cryptoUpdateAccount(updateTxnBody).build();
return context.dispatchComputeFees(synthTxn, context.payer());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import static com.hedera.node.app.service.contract.impl.test.TestHelpers.PARANOID_SOMEBODY;
import static com.hedera.node.app.service.contract.impl.test.TestHelpers.SOMEBODY;
import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.tuweniToPbjBytes;
import static com.hedera.node.app.service.contract.impl.utils.SynthTxnUtils.LAZY_CREATION_MEMO;
import static com.hedera.node.app.service.contract.impl.utils.SynthTxnUtils.synthHollowAccountCreation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
Expand All @@ -51,6 +52,7 @@
import com.hedera.hapi.node.base.Key;
import com.hedera.hapi.node.state.token.Account;
import com.hedera.hapi.node.token.CryptoTransferTransactionBody;
import com.hedera.hapi.node.token.CryptoUpdateTransactionBody;
import com.hedera.hapi.node.transaction.TransactionBody;
import com.hedera.node.app.service.contract.impl.exec.scope.HandleHederaNativeOperations;
import com.hedera.node.app.service.contract.impl.exec.scope.VerificationStrategy;
Expand All @@ -60,7 +62,9 @@
import com.hedera.node.app.service.token.ReadableTokenStore;
import com.hedera.node.app.service.token.api.TokenServiceApi;
import com.hedera.node.app.service.token.records.CryptoCreateRecordBuilder;
import com.hedera.node.app.spi.fees.Fees;
import com.hedera.node.app.spi.workflows.HandleContext;
import com.hedera.pbj.runtime.io.buffer.Bytes;
import java.util.function.Predicate;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -147,33 +151,64 @@ void getTokenUsesStore() {

@Test
void createsHollowAccountByDispatching() {
final var synthTxn = TransactionBody.newBuilder()
final var synthLazyCreate = TransactionBody.newBuilder()
.cryptoCreateAccount(synthHollowAccountCreation(CANONICAL_ALIAS))
.build();
given(context.payer()).willReturn(A_NEW_ACCOUNT_ID);

when(context.dispatchRemovablePrecedingTransaction(
eq(synthTxn), eq(CryptoCreateRecordBuilder.class), eq(null), eq(A_NEW_ACCOUNT_ID)))
eq(synthLazyCreate), eq(CryptoCreateRecordBuilder.class), eq(null), eq(A_NEW_ACCOUNT_ID)))
.thenReturn(cryptoCreateRecordBuilder);

final var synthLazyCreateFees = new Fees(1L, 2L, 3L);
given(context.dispatchComputeFees(synthLazyCreate, A_NEW_ACCOUNT_ID)).willReturn(synthLazyCreateFees);

final var synthFinalizatonFees = new Fees(4L, 5L, 6L);
final var synthFinalizationTxn = TransactionBody.newBuilder()
.cryptoUpdateAccount(CryptoUpdateTransactionBody.newBuilder()
.key(Key.newBuilder().ecdsaSecp256k1(Bytes.EMPTY)))
.build();
given(context.dispatchComputeFees(synthFinalizationTxn, A_NEW_ACCOUNT_ID))
.willReturn(synthFinalizatonFees);

given(cryptoCreateRecordBuilder.status()).willReturn(OK);

final var status = subject.createHollowAccount(CANONICAL_ALIAS);

assertEquals(OK, status);

verify(cryptoCreateRecordBuilder).memo(LAZY_CREATION_MEMO);
verify(cryptoCreateRecordBuilder)
.transactionFee(synthLazyCreateFees.totalFee() + synthFinalizatonFees.totalFee());
}

@Test
void createsHollowAccountByDispatchingDoesNotThrowErrors() {
final var synthTxn = TransactionBody.newBuilder()
final var synthLazyCreate = TransactionBody.newBuilder()
.cryptoCreateAccount(synthHollowAccountCreation(CANONICAL_ALIAS))
.build();
given(context.payer()).willReturn(A_NEW_ACCOUNT_ID);
given(context.dispatchRemovablePrecedingTransaction(
eq(synthTxn), eq(CryptoCreateRecordBuilder.class), eq(null), eq(A_NEW_ACCOUNT_ID)))
eq(synthLazyCreate), eq(CryptoCreateRecordBuilder.class), eq(null), eq(A_NEW_ACCOUNT_ID)))
.willReturn(cryptoCreateRecordBuilder);

final var synthLazyCreateFees = new Fees(1L, 2L, 3L);
given(context.dispatchComputeFees(synthLazyCreate, A_NEW_ACCOUNT_ID)).willReturn(synthLazyCreateFees);

final var synthFinalizatonFees = new Fees(4L, 5L, 6L);
final var synthFinalizationTxn = TransactionBody.newBuilder()
.cryptoUpdateAccount(CryptoUpdateTransactionBody.newBuilder()
.key(Key.newBuilder().ecdsaSecp256k1(Bytes.EMPTY)))
.build();
given(context.dispatchComputeFees(synthFinalizationTxn, A_NEW_ACCOUNT_ID))
.willReturn(synthFinalizatonFees);
given(cryptoCreateRecordBuilder.status()).willReturn(MAX_ENTITIES_IN_PRICE_REGIME_HAVE_BEEN_CREATED);

final var status = assertDoesNotThrow(() -> subject.createHollowAccount(CANONICAL_ALIAS));
assertThat(status).isEqualTo(MAX_ENTITIES_IN_PRICE_REGIME_HAVE_BEEN_CREATED);

verify(cryptoCreateRecordBuilder).memo(LAZY_CREATION_MEMO);
verify(cryptoCreateRecordBuilder)
.transactionFee(synthLazyCreateFees.totalFee() + synthFinalizatonFees.totalFee());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"specSnapshots":{"lazyCreateViaEthereumCryptoTransfer":{"placeholderNum":1155,"encodedItems":[{"b64Body":"Cg8KCQi20pGsBhDXCxICGAISAhgDIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6aAboECgIYeRILCPKg7K8GEOjnyjAipgQKKwolaGVkZXJhLmFsbG93YW5jZXMubWF4VHJhbnNhY3Rpb25MaW1pdBICMjAKJgoWdXBncmFkZS5hcnRpZmFjdHMucGF0aBIMZGF0YS91cGdyYWRlCh4KFWNvbnRyYWN0cy5ldm0udmVyc2lvbhIFdjAuMzQKMAoibGVkZ2VyLmF1dG9SZW5ld1BlcmlvZC5tYXhEdXJhdGlvbhIKMTAwMDAwMDAwMAoiChpsZWRnZXIubWF4QXV0b0Fzc29jaWF0aW9ucxIENTAwMAowChdiYWxhbmNlcy5leHBvcnREaXIucGF0aBIVZGF0YS9hY2NvdW50QmFsYW5jZXMvCi0KImxlZGdlci5hdXRvUmVuZXdQZXJpb2QubWluRHVyYXRpb24SBzY5OTk5OTkKJQodY3J5cHRvQ3JlYXRlV2l0aEFsaWFzLmVuYWJsZWQSBHRydWUKKAofZW50aXRpZXMubGltaXRUb2tlbkFzc29jaWF0aW9ucxIFZmFsc2UKJwofY29udHJhY3RzLmFsbG93QXV0b0Fzc29jaWF0aW9ucxIEdHJ1ZQocChRsYXp5Q3JlYXRpb24uZW5hYmxlZBIEdHJ1ZQoYChFjb250cmFjdHMuY2hhaW5JZBIDMjk4ChwKFHRva2Vucy5tYXhQZXJBY2NvdW50EgQxMDAwCigKIWhlZGVyYS5hbGxvd2FuY2VzLm1heEFjY291bnRMaW1pdBIDMTAw","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw2rDLxOtZFQMCwiwwfSMavBTm7BrtN3bTYYafYsDGuHq8RoreoeduC3knSFjZwkdiGgsI8tKRrAYQ4/jDOiIPCgkIttKRrAYQ1wsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"},{"b64Body":"Cg8KCQi20pGsBhDZCxICGAISAhgDGPuV9hQiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlo0CiISILPgdPvcEq1GRU50fE06m4foLm8UokMXb5hIREEzPgeWEICA9pamtogBSgUIgM7aAw==","b64Record":"CiUIFhIDGIQJKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjApHQjwstYKfgRHyve/9nOWW2wX1ATd5OBFC+4KhGTdfERzc/e1kzdNlzFhyNEUi/IaDAjy0pGsBhCz2uS8AiIPCgkIttKRrAYQ2QsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIfCg0KAhgCEP//663M7JACCg4KAxiECRCAgOytzOyQAg=="},{"b64Body":"ChEKCQi30pGsBhDbCxICGAIgAVpoCiM6IQOmvN/o1MoYnPcKEgZcSyVS9VermjAh8wgzWjBmS8DLKkoFCIDO2gNqFGF1dG8tY3JlYXRlZCBhY2NvdW50kgEjOiEDprzf6NTKGJz3ChIGXEslUvVXq5owIfMIM1owZkvAyyo=","b64Record":"CgcIFhIDGIUJEjCeFpR5KFMQCylcw5EPxd89pMA7iOuTUGeIfOeho0TvGE/3negPyU+KYkFcj6+Wvt0aCwjz0pGsBhD60IZEIhEKCQi30pGsBhDbCxICGAIgASoUYXV0by1jcmVhdGVkIGFjY291bnRSAKoBFMfR0783EfCTMbjvJQh2aGnnsRoF"},{"b64Body":"Cg8KCQi30pGsBhDbCxICGAISAhgDGKqQBSICCHgyIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOcj0KOwoKCgIYAhD/j9/ASgotCiUiIzohA6a83+jUyhic9woSBlxLJVL1V6uaMCHzCDNaMGZLwMsqEICQ38BK","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIw4eB5WkIjZRsj0UfMgFe1YYHT5AgXHzn9GD16alQFM8g85Uee+0lXhEuaqHwVun0HGgsI89KRrAYQ+9CGRCIPCgkIt9KRrAYQ2wsSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIZCgoKAhgCEP+P38BKCgsKAxiFCRCAkN/ASg=="},{"b64Body":"ChAKCQi30pGsBhDhCxIDGIQJEgIYAxjChwUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjpIDuQEKsAEC+K2CASqAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPooAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgwMNQJRT4IL57m1x4iLe1P/0fXXV3D++GIhFY5GCRPQAAIDAAaC/WZp3t1KVig1Y3fpJ7nrM5aiA88JjqB8TUAZkYtF67aB0wIlaxGUIDdqMdVswIeu1NMW5IjxLvNLYIyX039PYHBiAyrXuAQ==","b64Record":"CiAIHiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwsLvq1biaEzTAeS5Lrdq/g/ieQ4tAO5uDXpbt52626+BcJ3gu16HlPFi29KViWb9SGgwI89KRrAYQq/+DxgIiEAoJCLfSkawGEOELEgMYhAkqIMODwq7DgsK3w4PCuXRGOMOCwq5Kw4PCi8ODwpDDg8KOMILh5wY6JRoQSU5TVUZGSUNJRU5UX0dBUyjAmgxQwJoMWIDKte4BagMYhQlSKgoHCgIYAxCeLgoJCgIYYhD2ls4NCggKAxigBhDwfAoKCgMYhAkQg8LPDYoBIOvvt4J9sCBr2foAKul3j4hFfZbOQhenmWRuIPdyTefq"},{"b64Body":"ChIKCQi40pGsBhDjCxIDGIQJIAFaOAoCMgBKBQiAztoDahRsYXp5LWNyZWF0ZWQgYWNjb3VudJIBFFPggvnubXHiIt7U//R9ddXcP74Y","b64Record":"CgcIFhIDGIcJEjDioi9aG9jWrcsGf0y1obT1xEZ5Uaomg0Fm3e7AywL4WNb9pm9DrTwsgg1ifcoo4gYaCwj00pGsBhDiqdpJIhIKCQi40pGsBhDjCxIDGIQJIAEqFGxhenktY3JlYXRlZCBhY2NvdW50MInK5RJSAA=="},{"b64Body":"ChAKCQi40pGsBhDjCxIDGIQJEgIYAxjChwUiAgh4MiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjpIDuQEKsAEC+K2CASoBoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPooAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgx6EgJRT4IL57m1x4iLe1P/0fXXV3D++GIhFY5GCRPQAAIDAAaDCe+psti/ghMQLh5j3tzMFYW7ViXDEHynVTbKmNYfp9KB6BCgbe6r+R0soWNePmyDUisENdaLBImhdxATj/j7TNBiAyrXuAQ==","b64Record":"CiUIFiIDGIcJKhwKDAgBEAwaBgiArpmkDxIMCAEQDxoGCICumaQPEjD28eoGPGKreweEnp1faH5GW1kkWxivocVn47bYo9zxJEOxTbPJEAm807dh4bO84ngaCwj00pGsBhDjqdpJIhAKCQi40pGsBhDjCxIDGIQJKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjjDC05o2OpsCCgMYhwkigAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKIDUYVCAiXpYgMq17gFqAxiFCVJECgcKAhgDEJ4uCgkKAhhiEPb7s2wKCAoDGKAGEPB8CgoKAxiECRCDp7VsCgsKAxiFCRD/k+vcAwoLCgMYhwkQgJTr3AOKASCHGy7uUcFh6xS1ZqwjLOF8p9inQSRqES4CwNcEu8pi5A=="},{"b64Body":"Cg8KCQi50pGsBhCGDBICGAISAhgDIgIIeDIgw4PCrsOCwrfDg8K5dEY4w4LCrkrDg8KLw4PCkMODwo6aAboECgIYeRILCPWg7K8GENjtnzUipgQKKwolaGVkZXJhLmFsbG93YW5jZXMubWF4VHJhbnNhY3Rpb25MaW1pdBICMjAKJgoWdXBncmFkZS5hcnRpZmFjdHMucGF0aBIMZGF0YS91cGdyYWRlCh4KFWNvbnRyYWN0cy5ldm0udmVyc2lvbhIFdjAuMzgKMAoibGVkZ2VyLmF1dG9SZW5ld1BlcmlvZC5tYXhEdXJhdGlvbhIKMTAwMDAwMDAwMAoiChpsZWRnZXIubWF4QXV0b0Fzc29jaWF0aW9ucxIENTAwMAowChdiYWxhbmNlcy5leHBvcnREaXIucGF0aBIVZGF0YS9hY2NvdW50QmFsYW5jZXMvCi0KImxlZGdlci5hdXRvUmVuZXdQZXJpb2QubWluRHVyYXRpb24SBzY5OTk5OTkKJQodY3J5cHRvQ3JlYXRlV2l0aEFsaWFzLmVuYWJsZWQSBHRydWUKKAofZW50aXRpZXMubGltaXRUb2tlbkFzc29jaWF0aW9ucxIFZmFsc2UKJwofY29udHJhY3RzLmFsbG93QXV0b0Fzc29jaWF0aW9ucxIEdHJ1ZQocChRsYXp5Q3JlYXRpb24uZW5hYmxlZBIEdHJ1ZQoYChFjb250cmFjdHMuY2hhaW5JZBIDMjk4ChwKFHRva2Vucy5tYXhQZXJBY2NvdW50EgQxMDAwCigKIWhlZGVyYS5hbGxvd2FuY2VzLm1heEFjY291bnRMaW1pdBIDMTAw","b64Record":"CiAIFiocCgwIARAMGgYIgK6ZpA8SDAgBEA8aBgiArpmkDxIwtpaaLhWmJd20BeOJuuD1GOthZfZdheczN8KiHZeVOBpMskVKHeiK2gqhjeuLFlkSGgsI9dKRrAYQu6zUNSIPCgkIudKRrAYQhgwSAhgCKiDDg8Kuw4LCt8ODwrl0RjjDgsKuSsODwovDg8KQw4PCjlIA"}]}}}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@

package com.hedera.services.bdd.spec.utilops.domain;

import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS;

import com.google.protobuf.InvalidProtocolBufferException;
import com.hedera.services.stream.proto.RecordStreamItem;
import com.hederahashgraph.api.proto.java.FileID;
import com.hederahashgraph.api.proto.java.SignedTransaction;
import com.hederahashgraph.api.proto.java.TransactionBody;
import com.hederahashgraph.api.proto.java.TransactionRecord;
Expand All @@ -30,6 +33,9 @@
* @param itemRecord the transaction record
*/
public record ParsedItem(TransactionBody itemBody, TransactionRecord itemRecord) {
private static final FileID PROPERTIES_FILE_ID =
FileID.newBuilder().setFileNum(121).build();

public static ParsedItem parse(final RecordStreamItem item) throws InvalidProtocolBufferException {
final var txn = item.getTransaction();
final TransactionBody body;
Expand All @@ -42,4 +48,10 @@ public static ParsedItem parse(final RecordStreamItem item) throws InvalidProtoc
}
return new ParsedItem(body, item.getRecord());
}

public boolean isPropertyOverride() {
return itemRecord.getReceipt().getStatus() == SUCCESS
&& itemBody.hasFileUpdate()
&& PROPERTIES_FILE_ID.equals(itemBody.getFileUpdate().getFileID());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public void setEncodedItems(@NonNull final List<EncodedItem> encodedItems) {
}

public List<ParsedItem> parsedItems() {
return encodedItems.stream().map(EncodedItem::asParsedItem).toList();
return encodedItems.stream()
.map(EncodedItem::asParsedItem)
.filter(pi -> !pi.isPropertyOverride())
.toList();
}
}
Loading

0 comments on commit c7dd6e6

Please sign in to comment.