- All Superinterfaces:
AutoCloseable,io.hotmoka.closeables.api.OnCloseHandlersContainer
public interface Application
extends AutoCloseable, io.hotmoka.closeables.api.OnCloseHandlersContainer
An application for the Mokamint blockchain. It specifies the application layer
of a blockchain. Mokamint applications are the run-time support to filter
the transactions reaching a node and to execute sequential groups
of transactions, those inside a block of the blockchain. In particular,
a node executes the transactions inside a block at a given
The execution of a group of transactions is identified by a numerical
The implementation of all these methods must be deterministic. The execution of a group of transactions can depend only on
The method
height,
having a given deadline,
starting from the state whose identifier is initialStateId (which is
typically that at the end of the previous block), at a moment when,
by calling the API of its application as follows:
-
groupId = beginBlock(height, initialStateId, when); - for each transaction
txin the block, do:-
checkTransaction(tx); -
deliverTransaction(tx, groupId);
-
-
finalStateId = endBlock(groupId, deadline); -
commitBlock(groupId);
finalStateId. That is, that state will be recoverable
in the future, from finalStateId, if required by the node.
If, instead, the final state needn't be committed, because if won't be needed in the
future (for instance, because finalStateId does not match its expected
value and hence block verification fails), then abortBlock(int) is called
at the end, instead of commitBlock(int).
The execution of a group of transactions is identified by a numerical
groupId,
that should be unique among all currently ongoing executions. This is because the application
might be required to run more groups of transactions, concurrently, and each of those
executions must be identified by a different groupId. After the execution of
commitBlock(groupId) or abortBlock(groupId), that
groupId may be recycled for a subsequent execution.
The implementation of all these methods must be deterministic. The execution of a group of transactions can depend only on
height, deadline,
initialStateId and when.
The method
checkTransaction(Transaction) does not receive the identifier of the
group execution, since it performs a context-independent (and typically, consequently, superficial)
check, that is applied also as a filter before adding transactions to the mempool of a node.
Method deliverTransaction(int, Transaction) subsequently performs a more thorough consistency
check later, that considers the context of its execution (for instance, the state where the check is
performed). This is why both these methods can throw a TransactionRejectedException.-
Method Summary
Modifier and TypeMethodDescriptionvoidabortBlock(int groupId) The node calls this method to abort the execution of the group of transactions identified byid.intbeginBlock(long height, LocalDateTime when, byte[] stateId) The node calls this method at the start of the execution of the transactions inside a block.booleancheckPrologExtra(byte[] extra) Checks if the given extra data from the prolog of a deadline is considered valid by this application.voidcheckTransaction(Transaction transaction) Checks if the given transaction is valid according to this application.voidclose()Closes this application.voidcommitBlock(int groupId) The node calls this method to commit the state resulting at the end of the execution of the group of transactions identified byid.voiddeliverTransaction(int groupId, Transaction transaction) Delivers another transaction inside the group execution identified byid.byte[]The node calls this method when a group execution of transactions ends.byte[]Yields the identifier of the state of this application when it starts, before any transaction has been executed.longgetPriority(Transaction transaction) Computes the priority of the given transaction.getRepresentation(Transaction transaction) Yields a string representation of the transaction, that can be used to print or process its structure.voidkeepFrom(LocalDateTime start) Informs the application that states of blocks created with abeginBlock(long, LocalDateTime, byte[])whosewhenparameter is beforestartare allowed to be garbage-collected, if the application has some notion of garbage-collection.voidPublishes the given block, that has just been added to the blockchain.Methods inherited from interface io.hotmoka.closeables.api.OnCloseHandlersContainer
addOnCloseHandler, removeOnCloseHandler
-
Method Details
-
checkPrologExtra
boolean checkPrologExtra(byte[] extra) throws ClosedApplicationException, TimeoutException, InterruptedException Checks if the given extra data from the prolog of a deadline is considered valid by this application. This method is called whenever a node receives a new deadline from one of its miners. The application can decide to accept or reject the deadline, on the basis of its prolog's extra bytes. This allows applications to require a specific structure for the prologs of the valid deadlines. If this is not relevant for an application, it can just require this array to be any array or force it to be empty.- Parameters:
extra- the extra, application-specific bytes of the prolog- Returns:
- true if and only if
extrais valid according to this application - Throws:
ClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
checkTransaction
void checkTransaction(Transaction transaction) throws TransactionRejectedException, ClosedApplicationException, TimeoutException, InterruptedException Checks if the given transaction is valid according to this application. Invalid transactions are just rejected when added to a node and they will never be added to the mempool and consequently never to the blockchain. This check is called as soon as a transaction reaches a node. It is typically a simply syntactical, context-independent check. An application can safely implement this method as a no-operation, since it is only meant for a quick optimization: to discard transactions that are clearly invalid, avoiding pollution of the mempool and without even trying to deliver them.- Parameters:
transaction- the transaction to check- Throws:
TransactionRejectedException- if the check failed and the transaction should not be added to the mempoolClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
getPriority
long getPriority(Transaction transaction) throws TransactionRejectedException, ClosedApplicationException, TimeoutException, InterruptedException Computes the priority of the given transaction. Nodes may (but are not required to) implement a policy of transaction inclusion in blocks that favors transactions with higher priority.- Parameters:
transaction- the transaction- Returns:
- the priority of
transaction - Throws:
TransactionRejectedException- if the priority of the transaction cannot be computedClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
getRepresentation
String getRepresentation(Transaction transaction) throws TransactionRejectedException, ClosedApplicationException, TimeoutException, InterruptedException Yields a string representation of the transaction, that can be used to print or process its structure. This can be everything, possibly, but not necessarily, JSON. It is expected (but not required) that if a transaction passes thecheckTransaction(Transaction)test without throwing aTransactionRejectedException, thengetRepresentation(Transaction)will not throw that exception either.- Parameters:
transaction- the transaction- Returns:
- the representation of
transaction - Throws:
TransactionRejectedException- if the representation of the transaction cannot be computedClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
getInitialStateId
byte[] getInitialStateId() throws ClosedApplicationException, TimeoutException, InterruptedExceptionYields the identifier of the state of this application when it starts, before any transaction has been executed. This is typically the hash of the empty state of the application.- Returns:
- the identifier of the state of this application when it starts
- Throws:
ClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
beginBlock
int beginBlock(long height, LocalDateTime when, byte[] stateId) throws UnknownStateException, ClosedApplicationException, TimeoutException, InterruptedException The node calls this method at the start of the execution of the transactions inside a block. The application must be able to support the concurrent execution of more groups of transactions. Consequently, each execution is identified by a unique number.- Parameters:
height- the height of the block whose transactions are being executedwhen- the time at the beginning of the execution of the transactions in the blockstateId- the identifier of the state of the application at the beginning of the execution of the transactions in the block- Returns:
- the identifier of the group execution that is being started; this must be different from the identifier of other executions that are currently being performed
- Throws:
UnknownStateException- if the application cannot find the state with identifierstateIdClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
deliverTransaction
void deliverTransaction(int groupId, Transaction transaction) throws TransactionRejectedException, UnknownGroupIdException, ClosedApplicationException, TimeoutException, InterruptedException Delivers another transaction inside the group execution identified byid. This means that the transaction will be fully checked and then executed. If the full check fails, an exception is thrown instead. Fully checked means that the transaction could be completed verified in the context of the block. This is then a thorough, context-dependent check, must stronger, in general, than the check performed bycheckTransaction(Transaction).- Parameters:
groupId- the identifier of the group executiontransaction- the transaction to deliver- Throws:
TransactionRejectedException- if the check or execution of the transaction failedUnknownGroupIdException- if thegroupIdis not validClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
endBlock
byte[] endBlock(int groupId, Deadline deadline) throws ClosedApplicationException, UnknownGroupIdException, TimeoutException, InterruptedException The node calls this method when a group execution of transactions ends. This gives the application the opportunity of adding the effects of coinbase transactions that it should execute at the end of the execution of the transactions in the group. Such coinbase transactions are typically related to a deadline, that inside the block whose transactions have been executed, which is why the latter is provided to this method.- Parameters:
groupId- the identifier of the group execution of transactions that is being endeddeadline- the deadline that has been computed for the block containing the transactions- Returns:
- the identifier of the state resulting at the end of the group execution of the transactions, including eventual coinbase transactions added at its end
- Throws:
ClosedApplicationException- if the application is already closedUnknownGroupIdException- if thegroupIdis not validTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
commitBlock
void commitBlock(int groupId) throws ClosedApplicationException, UnknownGroupIdException, TimeoutException, InterruptedException The node calls this method to commit the state resulting at the end of the execution of the group of transactions identified byid. This means that the application, in the future, must be able to recover the state at the end of that execution, from the identifier of that state. This typically requires to commit the resulting state into a database.- Parameters:
groupId- the identifier of the execution of a group of transactions that is being committed- Throws:
UnknownGroupIdException- if thegroupIdis not validClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
abortBlock
void abortBlock(int groupId) throws ClosedApplicationException, UnknownGroupIdException, TimeoutException, InterruptedException The node calls this method to abort the execution of the group of transactions identified byid. This means that the application, in the future, will not be required to recover the state at the end of that execution, from the identifier of that state. This typically requires to abort a database transaction and clear some resources.- Parameters:
groupId- the identifier of the execution of a group of transactions that is being aborted- Throws:
UnknownGroupIdException- if thegroupIdis not validClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
keepFrom
void keepFrom(LocalDateTime start) throws ClosedApplicationException, TimeoutException, InterruptedException Informs the application that states of blocks created with abeginBlock(long, LocalDateTime, byte[])whosewhenparameter is beforestartare allowed to be garbage-collected, if the application has some notion of garbage-collection.- Parameters:
start- the limit time, before which states can be garbage-collected- Throws:
ClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
publish
Publishes the given block, that has just been added to the blockchain. The application might exploit this hook, for instance, in order to trigger events on the basis of the content of the block. Or it might just do nothing.- Parameters:
block- the block to publish- Throws:
ClosedApplicationException- if the application is already closedTimeoutException- if no answer arrives before a time windowInterruptedException- if the current thread is interrupted while waiting for an answer to arrive
-
close
void close()Closes this application. After this closure, the methods of this application will throw aClosedApplicationException. An application cannot be reopened after being closed.- Specified by:
closein interfaceAutoCloseable
-