Skip to main content
Version: 3.10

Manage the Contract and Function Lifecycle

This document explains the lifecycle of contracts and functions in ScalarDL—from creating and registering them to updating them when bug fixes or feature additions are needed.

Create a contract or function

In ScalarDL, you implement business logic as two types of Java programs: contracts and functions. Contracts manage tamper-evident asset records in the Ledger, while functions work alongside contracts to manage mutable records in an external database through ScalarDB.

To create a contract or function, write a Java class that extends one of the predefined base classes, such as JacksonBasedContract for contracts or JacksonBasedFunction for functions.

For details on how to write contracts and functions, see the following:

Register a contract or function

After creating a contract or function, you need to register it with ScalarDL before you can use it.

To register a contract:

scalardl register-contract --properties client.properties --contract-id StateUpdater --contract-binary-name com.org1.contract.StateUpdater --contract-class-file build/classes/java/main/com/org1/contract/StateUpdater.class

To register a function:

scalardl register-function --properties client.properties --function-id test-function --function-binary-name com.example.function.TestFunction --function-class-file /path/to/TestFunction.class

For details on registration commands and options, see ScalarDL Client Command Reference.

Contract registration constraints

When registering a contract, note the following constraints:

  • Unique contract ID: Each contract must have a unique contract ID. If you try to register a contract with an ID that already exists, the registration will fail.
  • Consistent binary name and byte code: If a binary name has already been registered with a certain byte code, you cannot register a different byte code under the same binary name. However, you can register the same binary name and byte code under a different client or a different contract ID.

Function registration constraints

Unlike contracts, functions can be re-registered with the same function ID. The behavior depends on how you access ScalarDL:

  • Privileged port (default: 50052): Functions can always be registered and overwritten without restrictions.
  • Non-privileged port (default: 50051): Function registration and overwriting are controlled by administrator settings.

Update a contract or function

Contracts and functions have fundamentally different update mechanisms because they serve different architectural roles in ScalarDL. Contracts manage tamper-evident asset records in the Ledger, and ScalarDL needs to be able to replay the full history of asset updates to validate consistency with past contract executions. For this reason, contracts are immutable (append-only). Functions, on the other hand, manage mutable records in an external database through ScalarDB, so there is no need to preserve the history of past function versions, and they can be overwritten.

Update a contract

Since contracts are immutable, you cannot modify or overwrite an existing contract. Instead, you must register a new version of the contract with a new contract ID and a new binary name.

Versioning best practices

There are two common approaches for versioning contracts:

Package-based versioning (recommended for production): Include the version number in the Java package name. The predefined contracts used internally by ScalarDL abstractions such as HashStore and TableStore also follow this approach.

For example, if your original contract is in com.example.contract.v1.StateUpdater, the updated version would be in com.example.contract.v2.StateUpdater. Similarly, the contract ID should reflect the version, such as v1.StateUpdater and v2.StateUpdater.

scalardl register-contract --properties client.properties --contract-id v2.StateUpdater --contract-binary-name com.example.contract.v2.StateUpdater --contract-class-file build/classes/java/main/com/example/contract/v2/StateUpdater.class

Class-name-based versioning (suitable for smaller scale or testing): Append the version number directly to the class name, such as StateUpdaterV2. This approach is simpler but can become less organized for large-scale projects.

scalardl register-contract --properties client.properties --contract-id StateUpdaterV2 --contract-binary-name com.example.contract.StateUpdaterV2 --contract-class-file build/classes/java/main/com/example/contract/StateUpdaterV2.class

Update your application code

After registering the new contract version, update your application code to use the new contract ID. For example, if you use ClientService, update the contract ID passed to the executeContract method.

note

Old contract versions remain registered in ScalarDL. This is by design—ScalarDL needs them for asset validation and history replay. Do not attempt to remove old contract versions.

Update a function

Since functions are mutable, you can update a function by re-registering it with the same function ID. The new byte code will overwrite the old one.

scalardl register-function --properties client.properties --function-id test-function --function-binary-name com.example.function.TestFunction --function-class-file /path/to/TestFunction.class

When overwriting a function, you can also change the binary name if needed. The function ID is the only identifier that must remain the same.

Execute updated contracts and functions

After updating a contract, use the new contract ID when executing it. The old contract ID still references the old version.

scalardl execute-contract --properties client.properties --contract-id v2.StateUpdater --contract-argument '{"asset_id":"some_asset", "state":3}'

After updating a function, you can use the same function ID as before, and the updated function will be executed automatically.

scalardl execute-contract --properties client.properties --contract-id v2.StateUpdater --contract-argument '{"asset_id":"some_asset", "state":3}' --function-id test-function --function-argument '{...}'

For details on executing contracts and functions, see the following:

See also