(image)

Programming Hotmoka
A tutorial on Hotmoka and smart contracts in Takamaka

3.6 Transactions can be added, posted and run

We have executed transactions on a Hotmoka node with methods addJarStoreTransaction(), addConstructorCallTransaction() and addInstanceMethodCallTransaction(). These methods, whose name starts with add, are synchronous, meaning that they block until the transaction is executed (or fails). If they are invoked on a node with a notion of commit, such as a blockchain, they guarantee to block until the transaction is actually committed. In many cases, when we immediately need the result of a transaction before continuing with the execution of the subsequent statements, these methods are the right choice. In many other cases, however, it is unnecessary to wait until the transaction has completed its execution and has been committed. In those cases, it can be faster to execute a transaction through a method whose name starts with post, such as postJarStoreTransaction(), postConstructorCallTransaction() or postInstanceMethodCallTransaction(). These methods are called asynchronous, since they terminate immediately, without waiting for the outcome of the transaction they trigger. Hence they cannot return their outcome immediately and return a future instead, whose get() value, if and when invoked, will block until the outcome of the transaction is finally available.

For instance, instead of the inefficient:

StorageValue s = node.addInstanceMethodCallTransaction
  (TransactionRequests.instanceMethodCall(
    signer,
    payer,
    nonce,
    chainId,
    BigInteger.valueOf(100_000),
    panarea(gasHelper.getSafeGasPrice()),
    family,
    MethodSignatures.ofNonVoid(PERSON, "toString", StorageTypes.STRING),
    einstein
  )).get();


// code that does not use s
// .....

one can write the more efficient:

MethodFuture future = node.postInstanceMethodCallTransaction
  (TransactionRequests.instanceMethodCall(
    signer,
    payer,
    nonce,
    chainId,
    BigInteger.valueOf(100_000),
    panarea(gasHelper.getSafeGasPrice()),
    family,
    MethodSignatures.ofNonVoid(PERSON, "toString", StorageTypes.STRING),
    einstein
  ));


// code that does not use s
// .....


// the following will be needed only if s is used later
StorageValue s = future.get().get();

where the first get() belongs to the future and is a blocking call that suspends until the method has been executed, and the second get() extracts the value from the optional returned by Hotmoka’s API for calling methods.

There is a third way to execute a transaction. Namely, calls to methods annotated as @View can be performed through the runInstanceMethodCallTransaction() (for instance methods) and runStaticMethodCallTransaction() (for static methods). As we have hinted before, these executions are performed locally, on the node they are addressed to, and do not add a transaction that must be replicated in each node of the network, for consensus, and that costs gas for storage. These executions are free and do not require a correct nonce, signature, or chain identifier, which is a great simplification.