LightWeight Contracts FAQ. Image Credit: Jason Rosewell, from Unplash.

Lightweight Contracts FAQ

Based on discussions with Ardor community members

See all lightweight contracts articles

Disclaimer: The lightweight contracts feature development is still evolving. The feature is currently deployed to testnet and some interfaces may still change.

Q: What is the contract runner?

A: The contract runner is an add-on, a server-side extension, which every node can choose if to run or not. When it’s running, it loads the contracts stored in the blockchain and execute them based on various conditions.

Q: How can I choose to execute a contract on my node?

A: You should configure the contract runner add-on in nxt.properties and the contracts.json configuration file. Any node owner can choose if and how to configure the contract settings. For example, each node will probably use different account passphrase to sign the transactions submitted by the contract and may configure the contract with different setup parameters.

Q: Can Nodes, running the contract runner add-on, choose which contracts to execute or will they execute any contract?

A: The contract runner will execute all the contracts for which there is a contract reference set for the contract runner account.

Q: What triggers contract execution?

A: Contracts are triggered either by sending them a transaction with a specific “trigger” message or with each new block.

Q: How is a contract represented on the blockchain?

A: Each contract is composed of two components, a cloud data transaction which stores the contract code itself and a contract reference which defines the contract unique name per account and provides setup parameters to the contract. The same contract code be referenced by different contract reference transactions from different accounts with different setup parameters.

Q: How does the contract runner select contracts to execute?

A: Three options:

1. For transaction-based contracts, it scans every new non-phased transaction or executed phased transaction for an attached trigger message which specifies the contract name. If it finds such a message, it invokes the contract to which it points through the contract reference, passing any optional invocation parameters embedded in the trigger message.

2. For block-based contracts, the node keeps a list of supported contracts and executes each one of them whenever it receives a new block.

3. Contracts can be invoked by the user using the invokeContract API which mimics the operation of 1 and 2. This API requires the admin password.

Q: If more than one node execute the same contract, what is the mechanism to avoid duplicate output transactions?

A: There is nothing that prevents more than one node from executing the same contract. In fact, this can be useful in many cases, and in most cases each of these nodes will use its own account passphrase to sign transactions generated by the contract. Node operators should make sure that they run the contract runner addon only on one node and that this node is always running, to avoid sending duplicate transactions from the contract, or to avoid not running the contract at all.

Q: How would account control increase the security of the contract?

A: When the contract account is under account control, a transaction submitted by a contract may trigger an automatic approval process on another node which controls the account. The other node will repeat the same calculation and compare its results with the transaction submitted by the contract. If there is a match, it will submit an approval transaction for the transaction submitted by the contract. Of course, this process can also be done manually.

Q: How can I review and validate the contract code?

A: If the source code is published, compile it and make sure you generate the exact same class file stored in the blockchain. If the source code is not published, download the class or jar file from the blockchain and decompile it using any standard Java IDE to review the code.

Q: Do you have to upload the binary .class file or can you upload a .java source file?

A: Currently you need to upload the .class file. In theory, you can also upload .java source code and the node will compile it into a .class file before running the contract, but this requires the nodes to run a Java JDK instead of JRE and this has more potential problems and attack vectors so it’s not supported at the moment.

Q: Can a contract submit multi-signature transaction (a.k.a phased transactions)?

A: Transactions submitted by a contract are normal transactions. A contract can be designed to submit only phased transactions, however this is up to the contract developer to decide. If the contract account is under account control then all transactions submitted by the contract are phased by default.

Q: Can several nodes run the same contract?

A: Sure, as long as each node uses a different account passphrase to sign transactions this can be useful. For example, an Oracle contract which records shipping costs or exchange rates on the blockchain can be deployed once and used by multiple nodes to record shipping costs between different locations, or exchange rates between different currency pairs, or different information providers. Most contracts will check some condition before they submit a transaction. For example, the RandomPayment contract verifies that the trigger transaction has sent an amount to its own account before sending back the random payment. Therefore, if it is deployed on 5 different nodes with 5 different accounts, then each of these nodes will respond to funds sent to a different account.

Q: So the contract is executed only by the account to which the trigger message is sent or by all nodes running the contract runner?

A: Potentially by all nodes. There can be contracts that execute without any trigger message, for example an Oracle service which checks the weather at some location every hour and records it in an account property, but someone will have to cover the transaction fees to update the account property in this case. As long as it makes sense for a service to run a contract and submit transactions they can deploy a contract triggered by every block or a contract triggered by a message transaction (or a message attached to any transaction type) sent to any account, not necessarily to their own account. For example, if the message is sent to an account with a certain property set by the contract account then the contact will execute its logic, otherwise it will ignore the message.

Q: What forces the contract “owner” to execute the contract?

A: Nothing, in fact, one weakness of this approach is that you may send an amount to the contract account but the contract account owner may never execute the triggered contract to provide you the service and just lock this amount. Therefore this mechanism requires some trust in the contract runner node. Of course, you can define that the funds are sent to an escrow account and only released to the contract account after it does some work, but then you need to trust the escrow account and develop a procedure to move funds from the escrow account to the contract account.

Q: Can you lock funds for a timeout period to cancel the trigger transaction so the funds go back to the sender?

A: You can use any feature already available on Ardor to set these conditions. Right now we do not provide transactions submitted by contracts any additional privileges or set any special restrictions on them.