com.hedera.node.app.spi.workflows.HandleContext Maven / Gradle / Ivy
/*
* Copyright (C) 2023-2024 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hedera.node.app.spi.workflows;
import static com.hedera.node.app.spi.workflows.HandleContext.TransactionCategory.SCHEDULED;
import static com.hedera.node.app.spi.workflows.record.ExternalizedRecordCustomizer.NOOP_EXTERNALIZED_RECORD_CUSTOMIZER;
import com.hedera.hapi.node.base.AccountID;
import com.hedera.hapi.node.base.HederaFunctionality;
import com.hedera.hapi.node.base.Key;
import com.hedera.hapi.node.base.SubType;
import com.hedera.hapi.node.transaction.TransactionBody;
import com.hedera.node.app.hapi.utils.throttles.DeterministicThrottle;
import com.hedera.node.app.spi.authorization.SystemPrivilege;
import com.hedera.node.app.spi.fees.ExchangeRateInfo;
import com.hedera.node.app.spi.fees.FeeAccumulator;
import com.hedera.node.app.spi.fees.FeeCalculator;
import com.hedera.node.app.spi.fees.Fees;
import com.hedera.node.app.spi.info.NetworkInfo;
import com.hedera.node.app.spi.records.BlockRecordInfo;
import com.hedera.node.app.spi.records.RecordCache;
import com.hedera.node.app.spi.signatures.SignatureVerification;
import com.hedera.node.app.spi.signatures.VerificationAssistant;
import com.hedera.node.app.spi.validation.AttributeValidator;
import com.hedera.node.app.spi.validation.ExpiryValidator;
import com.hedera.node.app.spi.workflows.record.ExternalizedRecordCustomizer;
import com.hedera.node.app.spi.workflows.record.RecordListCheckPoint;
import com.hedera.pbj.runtime.io.buffer.Bytes;
import com.swirlds.config.api.Configuration;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.time.Instant;
import java.util.List;
import java.util.function.Predicate;
/**
* Represents the context of a single {@code handle()}-call.
*
* The information and functionality provided by a {@code HandleContext} is valid only for the duration of the call. It
* can be grouped into five categories:
*
* - Information about the transaction being handled, such as its consensus time, its body, and its category
* - Configuration data and objects that depend on the current configuration
* - Verification data, that has been assembled during pre-handle
* - State related data and the possibility to rollback changes
* - Data related to the record stream
* - Functionality to dispatch preceding and child transactions
*
*/
@SuppressWarnings("UnusedReturnValue")
public interface HandleContext {
/**
* Category of the current transaction.
*/
enum TransactionCategory {
/** The original transaction submitted by a user. */
USER,
/** An independent, top-level transaction that is executed before the user transaction. */
PRECEDING,
/** A child transaction that is executed as part of a user transaction. */
CHILD,
/** A transaction executed via the schedule service. */
SCHEDULED
}
/**
* Returns the current consensus time.
*
* @return the current consensus time
*/
@NonNull
Instant consensusNow();
/**
* Returns the {@link TransactionBody}
*
* @return the {@code TransactionBody}
*/
@NonNull
TransactionBody body();
/**
* Gets the payer {@link AccountID}.
*
* @return the {@link AccountID} of the payer in this context
*/
@NonNull
AccountID payer();
/**
* Returns the current {@link Configuration} for the node.
*
* @return the {@code Configuration}
*/
@NonNull
Configuration configuration();
/**
* Returns information on current block and record file
*
* @return current BlockRecordInfo
*/
@NonNull
BlockRecordInfo blockRecordInfo();
/**
* Getter for the payer key
*
* @return the payer key
*/
@Nullable
Key payerKey();
/**
* Returns the Hedera resource prices (in thousandths of a tinycent) for the given {@link SubType} of
* the given {@link HederaFunctionality}. The contract service needs this information to determine both the
* gas price and the cost of storing logs (a function of the {@code rbh} price, which may itself vary by
* contract operation type).
*
* @param functionality the {@link HederaFunctionality} of interest
* @param subType the {@link SubType} of interest
* @return the corresponding Hedera resource prices
*/
@NonNull
FunctionalityResourcePrices resourcePricesFor(
@NonNull final HederaFunctionality functionality, @NonNull final SubType subType);
/**
* Get a calculator for calculating fees for the current transaction, and its {@link SubType}. Most transactions
* just use {@link SubType#DEFAULT}, but some (such as crypto transfer) need to be more specific.
*
* @param subType The {@link SubType} of the transaction.
* @return The {@link FeeCalculator} to use.
*/
@NonNull
FeeCalculator feeCalculator(@NonNull final SubType subType);
/**
* Gets a {@link FeeAccumulator} used for collecting fees for the current transaction.
*
* @return The {@link FeeAccumulator} to use.
*/
@NonNull
FeeAccumulator feeAccumulator();
/**
* Gets a {@link ExchangeRateInfo} which provides information about the current exchange rate.
*
* @return The {@link ExchangeRateInfo} .
*/
@NonNull
ExchangeRateInfo exchangeRateInfo();
/**
* Consumes and returns the next entity number, for use by handlers that create entities.
*
* If this method is called after a child transaction was dispatched, which is subsequently rolled back,
* the counter will be rolled back, too. Consequently, the provided number must not be used anymore in this case,
* because it will be reused.
*
* @return the next entity number
*/
long newEntityNum();
/**
* Peeks at the next entity number, for use by handlers that create entities.
*
*
If this method is called after a child transaction was dispatched, which is subsequently rolled back,
* the counter will be rolled back, too. Consequently, the provided number must not be used anymore in this case,
* because it will be reused.
*
* @return the next entity number
*/
long peekAtNewEntityNum();
/**
* Returns the validator for attributes of entities created or updated by handlers.
*
* @return the validator for attributes
*/
@NonNull
AttributeValidator attributeValidator();
/**
* Returns the validator for expiry metadata (both explicit expiration times and auto-renew configuration) of
* entities created or updated by handlers.
*
* @return the validator for expiry metadata
*/
@NonNull
ExpiryValidator expiryValidator();
/**
* Returns all (required and optional) keys of a nested transaction.
*
* @param nestedTxn the {@link TransactionBody} which keys are needed
* @param payerForNested the payer for the nested transaction
* @return the set of keys
* @throws PreCheckException If there is a problem with the nested transaction
*/
@NonNull
TransactionKeys allKeysForTransaction(@NonNull TransactionBody nestedTxn, @NonNull AccountID payerForNested)
throws PreCheckException;
/**
* Gets the {@link SignatureVerification} for the given key. If this key was not provided during pre-handle, then
* there will be no corresponding {@link SignatureVerification}. If the key was provided during pre-handle, then the
* corresponding {@link SignatureVerification} will be returned with the result of that verification operation.
*
*
The signatures of required keys are guaranteed to be verified. Optional signatures may still be in the
* process of being verified (and therefore may time out). The timeout can be configured via the configuration
* {@code hedera.workflow.verificationTimeoutMS}
*
* @param key the key to get the verification for
* @return the verification for the given key
* @throws NullPointerException if {@code key} is {@code null}
*/
@NonNull
SignatureVerification verificationFor(@NonNull Key key);
/**
* Gets the {@link SignatureVerification} for the given key. If this key was not provided during pre-handle, then
* there will be no corresponding {@link SignatureVerification}. If the key was provided during pre-handle, then the
* corresponding {@link SignatureVerification} will be returned with the result of that verification operation.
* Additionally, the VerificationAssistant provided may modify the result for "primitive", "Contract ID", or
* "Delegatable Contract ID" keys, and will be called to observe and reply for each such key as it is processed.
*
*
The signatures of required keys are guaranteed to be verified. Optional signatures may still be in the
* process of being verified (and therefore may time out). The timeout can be configured via the configuration
* {@code hedera.workflow.verificationTimeoutMS}
*
* @param key the key to get the verification for
* @param callback a VerificationAssistant callback function that will observe each "primitive", "Contract ID", or
* "Delegatable Contract ID" key and return a boolean indicating if the given key should be considered valid.
* @return the verification for the given key
*/
@NonNull
SignatureVerification verificationFor(@NonNull Key key, @NonNull VerificationAssistant callback);
/**
* Gets the {@link SignatureVerification} for the given hollow account.
*
*
The signatures of required accounts are guaranteed to be verified. Optional accounts may still be in the
* process of being verified (and therefore may time out). The timeout can be configured via the configuration
* {@code hedera.workflow.verificationTimeoutMS}
*
* @param evmAlias The evm alias to lookup verification for.
* @return the verification for the given hollow account.
* @throws NullPointerException if {@code evmAlias} is {@code null}
*/
@NonNull
SignatureVerification verificationFor(@NonNull final Bytes evmAlias);
/**
* Checks whether the payer of the current transaction refers to a superuser.
*
* @return {@code true} if the payer is a superuser, otherwise {@code false}
*/
boolean isSuperUser();
/**
* Checks whether the current transaction is a privileged transaction and the payer has sufficient rights.
*
* @return the {@code SystemPrivilege} of the current transaction
*/
SystemPrivilege hasPrivilegedAuthorization();
/** Gets the {@link RecordCache}. */
@NonNull
RecordCache recordCache();
/**
* Get a readable store given the store's interface. This gives read-only access to the store.
*
* @param storeInterface The store interface to find and create a store for
* @param Interface class for a Store
* @return An implementation of the provided store interface
* @throws IllegalArgumentException if the storeInterface class provided is unknown to the app
* @throws NullPointerException if {@code storeInterface} is {@code null}
*/
@NonNull
T readableStore(@NonNull Class storeInterface);
/**
* Return a writable store given the store's interface. This gives write access to the store.
*
* This method is limited to stores that are part of the transaction's service.
*
* @param storeInterface The store interface to find and create a store for
* @param Interface class for a Store
* @return An implementation of the provided store interface
* @throws IllegalArgumentException if the storeInterface class provided is unknown to the app
* @throws NullPointerException if {@code storeInterface} is {@code null}
*/
@NonNull
T writableStore(@NonNull Class storeInterface);
/**
* Return a service API given the API's interface. This permits use of another service
* that doesn't have a corresponding HAPI {@link TransactionBody}.
*
* @param apiInterface The API interface to find and create an implementation of
* @param Interface class for an API
* @return An implementation of the provided API interface
* @throws IllegalArgumentException if the apiInterface class provided is unknown to the app
* @throws NullPointerException if {@code apiInterface} is {@code null}
*/
@NonNull
T serviceApi(@NonNull Class apiInterface);
/**
* Returns the information about the network this transaction is being handled in.
*
* @return the network information
*/
@NonNull
NetworkInfo networkInfo();
/**
* Returns a record builder for the given record builder subtype.
*
* @param recordBuilderClass the record type
* @param the record type
* @return a builder for the given record type
* @throws NullPointerException if {@code recordBuilderClass} is {@code null}
* @throws IllegalArgumentException if the record builder type is unknown to the app
*/
@NonNull
T recordBuilder(@NonNull Class recordBuilderClass);
/**
* Dispatches the fee calculation for a child transaction (that might then be dispatched).
*
* The override payer id still matters for this purpose, because a transaction can add
* state whose lifetime is scoped to a payer account (the main current example is a
* {@link HederaFunctionality#CRYPTO_APPROVE_ALLOWANCE} dispatch).
*
* @param txBody the {@link TransactionBody} of the child transaction to compute fees for
* @param syntheticPayerId the child payer
* @param computeDispatchFeesAsTopLevel for mono fidelity, whether to compute fees as a top-level transaction
* @return the calculated fees
*/
Fees dispatchComputeFees(
@NonNull TransactionBody txBody,
@NonNull AccountID syntheticPayerId,
@NonNull ComputeDispatchFeesAsTopLevel computeDispatchFeesAsTopLevel);
/**
* Dispatches an independent (top-level) transaction, that precedes the current transaction.
*
*
A top-level transaction is independent of any other transaction. If it is successful, the state changes are
* automatically committed. If it fails, any eventual state changes are automatically rolled back.
*
*
This method can only be called my a {@link TransactionCategory#USER}-transaction and only as long as no state
* changes have been introduced by the user transaction (either by storing state or by calling a child
* transaction).
*
*
If non-null, the provided {@link Predicate} callback will be called to enforce signing requirements; or to
* verify simple keys when the child transaction calls any of the {@code verificationFor} methods. If the callback
* is null, no signing requirements will be enforced.
*
* @param txBody the {@link TransactionBody} of the transaction to dispatch
* @param recordBuilderClass the record builder class of the transaction
* @param verifier if signing requirements should be enforced, a {@link Predicate} that will be used to validate primitive keys
* @param syntheticPayer the payer of the transaction
* @return the record builder of the transaction
* @throws NullPointerException if {@code txBody} is {@code null}
* @throws IllegalArgumentException if the transaction is not a {@link TransactionCategory#USER}-transaction or if
* the record builder type is unknown to the app
* @throws IllegalStateException if the current transaction has already introduced state changes
*/
@NonNull
T dispatchPrecedingTransaction(
@NonNull TransactionBody txBody,
@NonNull Class recordBuilderClass,
@Nullable Predicate verifier,
AccountID syntheticPayer);
/**
* Dispatches a preceding transaction that already has an ID.
*
* @param txBody the {@link TransactionBody} of the transaction to dispatch
* @param recordBuilderClass the record builder class of the transaction
* @param verifier a {@link Predicate} that will be used to validate primitive keys
* @return the record builder of the transaction
* @param the record type
* @throws IllegalArgumentException if the transaction body did not have an id
*/
default T dispatchPrecedingTransaction(
@NonNull final TransactionBody txBody,
@NonNull final Class recordBuilderClass,
@NonNull final Predicate verifier) {
throwIfMissingPayerId(txBody);
return dispatchPrecedingTransaction(
txBody,
recordBuilderClass,
verifier,
txBody.transactionIDOrThrow().accountIDOrThrow());
}
/**
* Dispatches preceding transaction that can be reverted.
*
* A reversible preceding transaction depends on the current transaction. That means if the user transaction
* fails, a reversible preceding transaction is automatically rolled back. The state changes introduced by a
* reversible preceding transaction are automatically committed together with the parent transaction.
*
*
This method can only be called by a {@link TransactionCategory#USER}-transaction and only as long as no state
* changes have been introduced by the user transaction (either by storing state or by calling a child
* transaction).
*
*
The provided {@link Predicate} callback will be called to verify simple keys when the child transaction calls
* any of the {@code verificationFor} methods.
*
* @param txBody the {@link TransactionBody} of the transaction to dispatch
* @param recordBuilderClass the record builder class of the transaction
* @param verifier a {@link Predicate} that will be used to validate primitive keys
* @param syntheticPayer the payer of the transaction
* @return the record builder of the transaction
* @throws NullPointerException if {@code txBody} is {@code null}
* @throws IllegalArgumentException if the transaction is not a {@link TransactionCategory#USER}-transaction or if
* the record builder type is unknown to the app
* @throws IllegalStateException if the current transaction has already introduced state changes
*/
@NonNull
T dispatchReversiblePrecedingTransaction(
@NonNull TransactionBody txBody,
@NonNull Class recordBuilderClass,
@NonNull Predicate verifier,
AccountID syntheticPayer);
/**
* Dispatches preceding transaction that can be removed.
*
* A removable preceding transaction depends on the current transaction. That means if the user transaction
* fails, a removable preceding transaction is automatically removed and not exported. The state changes introduced by a
* removable preceding transaction are automatically committed together with the parent transaction.
*
*
This method can only be called by a {@link TransactionCategory#USER}-transaction and only as long as no state
* changes have been introduced by the user transaction (either by storing state or by calling a child
* transaction).
*
*
The provided {@link Predicate} callback will be called to verify simple keys when the child transaction calls
* any of the {@code verificationFor} methods.
*
* @param txBody the {@link TransactionBody} of the transaction to dispatch
* @param recordBuilderClass the record builder class of the transaction
* @param verifier if non-null, a {@link Predicate} that will be used to validate primitive keys
* @param syntheticPayer the payer of the transaction
* @return the record builder of the transaction
* @throws NullPointerException if {@code txBody} is {@code null}
* @throws IllegalArgumentException if the transaction is not a {@link TransactionCategory#USER}-transaction or if
* the record builder type is unknown to the app
* @throws IllegalStateException if the current transaction has already introduced state changes
*/
@NonNull
T dispatchRemovablePrecedingTransaction(
@NonNull TransactionBody txBody,
@NonNull Class recordBuilderClass,
@Nullable Predicate verifier,
AccountID syntheticPayer);
/**
* Dispatches a reversible preceding transaction that already has an ID.
*
* @param txBody the {@link TransactionBody} of the transaction to dispatch
* @param recordBuilderClass the record builder class of the transaction
* @param verifier a {@link Predicate} that will be used to validate primitive keys
* @return the record builder of the transaction
* @param the record type
* @throws IllegalArgumentException if the transaction body did not have an id
*/
default T dispatchReversiblePrecedingTransaction(
@NonNull final TransactionBody txBody,
@NonNull final Class recordBuilderClass,
@NonNull final Predicate verifier) {
throwIfMissingPayerId(txBody);
return dispatchReversiblePrecedingTransaction(
txBody,
recordBuilderClass,
verifier,
txBody.transactionIDOrThrow().accountIDOrThrow());
}
/**
* Dispatches a child transaction.
*
* A child transaction depends on the current transaction. That means if the current transaction fails,
* a child transaction is automatically rolled back. The state changes introduced by a child transaction are
* automatically committed together with the parent transaction.
*
*
A child transaction will run with the current state. It will see all state changes introduced by the current
* transaction or preceding child transactions. If successful, a new entry will be added to the
* {@link SavepointStack}. This enables the current transaction to commit or roll back the state changes. Please be
* aware that any state changes introduced by storing data in one of the stores after calling a child transaction
* will also be rolled back if the child transaction is rolled back.
*
*
The provided {@link Predicate} callback will be called to verify simple keys when the child transaction calls
* any of the {@code verificationFor} methods.
*
*
A {@link TransactionCategory#PRECEDING}-transaction must not dispatch a child transaction.
*
* @param txBody the {@link TransactionBody} of the child transaction to dispatch
* @param recordBuilderClass the record builder class of the child transaction
* @param callback a {@link Predicate} callback function that will observe each primitive key
* @param syntheticPayerId the payer of the child transaction
* @param childCategory the category of the child transaction
* @return the record builder of the child transaction
* @throws NullPointerException if any of the arguments is {@code null}
* @throws IllegalArgumentException if the current transaction is a
* {@link TransactionCategory#PRECEDING}-transaction or if the record builder type is unknown to the app
*/
@NonNull
T dispatchChildTransaction(
@NonNull TransactionBody txBody,
@NonNull Class recordBuilderClass,
@Nullable Predicate callback,
@NonNull AccountID syntheticPayerId,
@NonNull TransactionCategory childCategory);
/**
* Dispatches a child transaction that already has a transaction ID due to
* its construction in the schedule service.
*
* @param txBody the {@link TransactionBody} of the child transaction to dispatch
* @param recordBuilderClass the record builder class of the child transaction
* @param callback a {@link Predicate} callback function that will observe each primitive key
* @return the record builder of the child transaction
* @param the record type
* @throws IllegalArgumentException if the transaction body did not have an id
*/
@NonNull
default T dispatchScheduledChildTransaction(
@NonNull final TransactionBody txBody,
@NonNull final Class recordBuilderClass,
@NonNull final Predicate callback) {
throwIfMissingPayerId(txBody);
return dispatchChildTransaction(
txBody,
recordBuilderClass,
callback,
txBody.transactionIDOrThrow().accountIDOrThrow(),
SCHEDULED);
}
/**
* Dispatches a removable child transaction.
*
* A removable child transaction depends on the current transaction. It behaves in almost all aspects like a
* regular child transaction (see {@link #dispatchChildTransaction(TransactionBody, Class, Predicate, AccountID, TransactionCategory)}.
* But unlike regular child transactions, the records of removable child transactions are removed and not reverted.
*
*
The provided {@link Predicate} callback will be called to verify simple keys when the child transaction calls
* any of the {@code verificationFor} methods.
*
*
A {@link TransactionCategory#PRECEDING}-transaction must not dispatch a child transaction.
*
* @param txBody the {@link TransactionBody} of the child transaction to dispatch
* @param recordBuilderClass the record builder class of the child transaction
* @param callback a {@link Predicate} callback function that will observe each primitive key
* @param syntheticPayerId the payer of the child transaction
* @param customizer a final transformation to apply before externalizing if the returned value is non-null
* @return the record builder of the child transaction
* @throws NullPointerException if any of the arguments is {@code null}
* @throws IllegalArgumentException if the current transaction is a
* {@link TransactionCategory#PRECEDING}-transaction or if the record builder type is unknown to the app
*/
@NonNull
T dispatchRemovableChildTransaction(
@NonNull TransactionBody txBody,
@NonNull Class recordBuilderClass,
@Nullable Predicate callback,
@NonNull AccountID syntheticPayerId,
@NonNull ExternalizedRecordCustomizer customizer);
/**
* Dispatches a removable child transaction that already has a transaction ID.
*
* @param txBody the {@link TransactionBody} of the child transaction to dispatch
* @param recordBuilderClass the record builder class of the child transaction
* @param callback a {@link Predicate} callback function that will observe each primitive key
* @return the record builder of the child transaction
* @param the record type
* @throws IllegalArgumentException if the transaction body did not have an id
*/
@NonNull
default T dispatchRemovableChildTransaction(
@NonNull final TransactionBody txBody,
@NonNull final Class recordBuilderClass,
@NonNull final Predicate callback) {
throwIfMissingPayerId(txBody);
return dispatchRemovableChildTransaction(
txBody,
recordBuilderClass,
callback,
txBody.transactionIDOrThrow().accountIDOrThrow(),
NOOP_EXTERNALIZED_RECORD_CUSTOMIZER);
}
/**
* Adds a child record builder to the list of record builders. If the current {@link HandleContext} (or any parent
* context) is rolled back, all child record builders will be reverted.
*
* @param recordBuilderClass the record type
* @return the new child record builder
* @param the record type
* @throws NullPointerException if {@code recordBuilderClass} is {@code null}
* @throws IllegalArgumentException if the record builder type is unknown to the app
*/
@NonNull
T addChildRecordBuilder(@NonNull Class recordBuilderClass);
/**
* Adds a preceding child record builder to the list of record builders. If the current {@link HandleContext} (or any parent
* context) is rolled back, all child record builders will be reverted.
*
* @param recordBuilderClass the record type
* @return the new child record builder
* @param the record type
* @throws NullPointerException if {@code recordBuilderClass} is {@code null}
* @throws IllegalArgumentException if the record builder type is unknown to the app
*/
@NonNull
T addPrecedingChildRecordBuilder(@NonNull Class recordBuilderClass);
/**
* Adds a removable child record builder to the list of record builders. Unlike a regular child record builder,
* a removable child record builder is removed, if the current {@link HandleContext} (or any parent context) is
* rolled back.
*
* @param recordBuilderClass the record type
* @return the new child record builder
* @param the record type
* @throws NullPointerException if {@code recordBuilderClass} is {@code null}
* @throws IllegalArgumentException if the record builder type is unknown to the app
*/
@NonNull
T addRemovableChildRecordBuilder(@NonNull Class recordBuilderClass);
/**
* Returns the current {@link SavepointStack}.
*
* @return the current {@code TransactionStack}
*/
@NonNull
SavepointStack savepointStack();
/**
* Revert the childRecords from the checkpoint.
*/
void revertRecordsFrom(@NonNull RecordListCheckPoint recordListCheckPoint);
/**
* Verifies if the throttle in this operation context has enough capacity to handle the given number of the
* given function at the given time. (The time matters because we want to consider how much
* will have leaked between now and that time.)
*
* @param n the number of the given function
* @param function the function
* @return true if the system should throttle the given number of the given function
* at the instant for which throttling should be calculated
*/
boolean shouldThrottleNOfUnscaled(int n, HederaFunctionality function);
/**
* For each following child transaction consumes the capacity
* required for that child transaction in the consensus throttle buckets.
*
* @return true if all the child transactions were allowed through the throttle consideration, false otherwise.
*/
boolean hasThrottleCapacityForChildTransactions();
/**
* Create a checkpoint for the current childRecords.
*
* @return the checkpoint for the current childRecords, containing the first preceding record and the last following
* record.
*/
@NonNull
RecordListCheckPoint createRecordListCheckPoint();
/**
* Returns a list of snapshots of the current usage of all active throttles.
* @return the active snapshots
*/
List getUsageSnapshots();
/**
* Resets the current usage of all active throttles to the given snapshots.
*
* @param snapshots the snapshots to reset to
*/
void resetUsageThrottlesTo(List snapshots);
/**
* Returns whether the current transaction being processed was submitted by this node.
*
* @return true if the current transaction was submitted by this node
*/
boolean isSelfSubmitted();
/**
* A stack of savepoints.
*
* A new savepoint can be created manually. In addition, a new entry is added to the savepoint stack every time
* a child transaction is dispatched and executed successfully. The transaction stack allows to rollback an
* arbitrary number of transactions. Please be aware that rolling back a child transaction will also rollbacks all
* state changes that were introduced afterward.
*/
interface SavepointStack {
/**
* Create a savepoint manually.
*
* This method will add a new entry to the savepoint stack. A subsequent rollback will roll back all state
* changes that were introduced after the savepoint was added.
*/
void createSavepoint();
/**
* Commits all changes since the last savepoint.
*
* @throws IllegalStateException if the savepoint stack is empty
*/
void commit();
/**
* Rolls back the changes up until the last savepoint.
*
* @throws IllegalStateException if the savepoint stack is empty
*/
void rollback();
/**
* Returns the depth of the savepoint stack.
*
* @return the depth of the savepoint stack
*/
int depth();
}
static void throwIfMissingPayerId(@NonNull final TransactionBody body) {
if (!body.hasTransactionID() || !body.transactionIDOrThrow().hasAccountID()) {
throw new IllegalArgumentException("Transaction id must be set if dispatching without an explicit payer");
}
}
/**
* Returns the freeze time from state, if it is set.
* @return the freeze time, if it is set
*/
@Nullable
Instant freezeTime();
}