Execution Engines
Execution Engines are specialized nodes that detect and run designated off-chain components embedded in smart contracts. Execution Engines runs the Off-Chain Component in an asynchronous manner on a server distinct from the blockchain.
When you boot a deployment of the platform, it includes four Execution Engine nodes which listen to all public contracts.
This article explains how to run Execution Engines.
- First, we explain the configuration of Execution Engines,
- Second, you'll learn how to boot new Execution Engine nodes, and how to configure them to listen to specific contracts.
- Finally, we show an example of an Execution Engine in action with the Off-chain Secret Sharing contract.
Execution Engine Configuration
Execution Engines share the same configuration, which enables them to act as contract-listening servers.
The configuration contains fields for:
- Listening to the blockchain:
"readerNodeEndpoint"
,"tcpReaderAddresses"
(The flooding network addresses of reader nodes to listen to for contract updates). These allow the engine to track contract updates and blockchain state changes. The"tcpReaderAddresses"
have the formatbase64_pubkey:host:port
, and in particular contains the public keys corresponding to the readers'externalListenerKey
. - Interacting with the blockchain:
"transactionPrivateKey"
. This sets the identity of the engine on the blockchain, and is used for authentication, both with the blockchain, and with the smart contract. - Being interacted with by users over HTTP:
"restEndpointPort"
. Allows the engine to receive HTTP requests. - Interacting with other engines over TCP:
"tcpNetworkPrivateKey"
, and"engineNetworkTcpAddress"
are used for communication between execution engine nodes. - Specifying contracts to run:
"contractFilter"
. The field specifies which contracts the node should listen to, either contract addresses or contract types, for example"ZK"
,"SYSTEM"
or"PUBLIC"
, or a combination of these.
You can read more about these configuration parameters in the javadoc documentation.
Execution Engine configuration example
{
"restEndpointPort": "8400",
"readerNodeEndpoint": "http://reader-node:9432",
"storagePath": "target/reader",
"tcpReaderAddresses": ["AyIQ/K5j8m6Xp8+HjiA7ffVbQRzVgtWjUvLgBabn8b+G:reader-node:9111"],
"transactionPrivateKey": "0123456789ABCDEF",
"tcpNetworkPrivateKey": "FF0123456789ABCDEF",
"engineNetworkTcpAddress": "localhost:8410",
"contractFilter": ["PUBLIC"]
}
Starting and Connecting an Execution Engine
You can always add a new Execution Engine node to a running deployment of the platform, by following these steps:
- Add a configuration file for the Execution Engine.
- Create a .yaml file and add a container with an execution container image
registry.gitlab.com/secata/platform/platform-dev-runner/execution-container-standalone:latest
and the configuration file from step 1. See an example below. - Boot your Execution Engine container by running the command:
docker compose -f your-filename.yaml up -d
.
A minimal container for an Execution Engine node
ee-node:
container_name: ee-node
image: registry.gitlab.com/secata/platform/platform-dev-runner/execution-container-standalone:latest
volumes:
- ./conf/ee-node.json:/conf/server.json
ports:
- '8400:8400'
The ports
should match the "restEndpointPort"
in the configuration file.
To ensure the execution node starts successfully and is able to connect to a reader node, check the docker logs for the container by running the command:
docker logs ee-node
When an execution engine node is started, it listens to all the contracts described by the "contractFilter"
field
in its configuration.
Info
If the smart contract uses authentication, new Execution Engine nodes will be rejected unless explicitly trusted.
Ensure your contract logic supports dynamic node authorization or redeploy with updated node info.
To make a running execution engine node listen to a new smart contract, change the "contractFilter"
field in the configuration
and reboot the node. Specifically, add the address of the smart contract to the "contractFilter"
.
Example: Off-chain Secret Sharing with an Execution Engine node
To see the execution engines in action, these Java code examples show you how to use an execution node with the Off-chain Secret Sharing smart contract. This smart contract allows users to store secret shares.
First, register an intention of storing a secret share on chain with the register_sharing
action.
Then upload the shares to the off-chain components configured in the contract state.
Later, you can download the shares again from the off-chain components.
To try this out, first deploy an Off-chain Secret Sharing smart contract with the address(es) of the Execution Engine(s) node you are using.
For example, the address "00b7c90c48ad7a6a0ed058fc286ae11230fa8c8500"
corresponds to the address of the Execution Engine with private key 123456789ABCDEF
.
Register a sharing with an integer id.
Then, run the example code to upload a secret of your choice, to the sharing with your chosen id. This will upload a Secret Sharing, i.e. each Execution Engine will get a share through a put-request.
Finally, you can download the secret again. This works by sending get-requests to each Execution Engine.
Info
Remember to change the placeholder variables in the code to match your own.
-
The
READER_NODE_ENDPOINT
. If you are using the platform-dev-runner initial setup, the reader node endpoint is"http://localhost:9432"
. -
The contract address should be the address of the deployed Off-chain Secret Sharing smart contract.
-
Use your own private key as the
SENDER_KEY
.