Skip to content

Using Off-Chain Components in an Application

Off-Chain Components are subsystems of a smart contract that are automatically run by a special type of node called an Execution Engine.

These Engines provide HTTP endpoints to communicate with Off-Chain Components that the Engine is responsible for, which allows users and applications to send requests confidentially to smart contracts without having to publish the data on the blockchain.

These HTTP endpoints can be used to build confidential and auditable Key Management Services and Secret-sharing Services, with customizable authentication and secret-sharing protocols.

Connecting to an Execution Engine

While some Execution Engines can be run without any HTTP endpoints, most will want to expose their endpoints to allow incoming connections.

Once exposed, the Off-Chain Component can be accessed through and endpoint with the following format:

https://<EE HOSTNAME>/executioncontainer/<CONTRACT ADDRESS>/<CONTRACT SPECIFIC PATH>

Where <EE HOSTNAME> is the individual execution engine's hostname, <CONTRACT ADDRESS> is the contract's on-chain Address, and <CONTRACT SPECIFIC PATH> can be anything that the off-chain component specifies.

Example: Downloading from an Off-Chain Component

Data download should generally be done using a GET request.

Assume that you want to get the resource /index.html from the contract with Address 010123456789ABCDEF0123456789ABCDEF01234567, and you know the endpoint of the Execution Engines as example.org. Then you could use the following cURL command:

curl https://example.org/executioncontainer/010123456789ABCDEF0123456789ABCDEF01234567/index.html

The recipient contract's off-chain defines the format of the request and response. This example assumes a contract without authentication. If the contract is authenticated you will possibly need to include a header that performs the autentication.

Example: Uploading to an Off-Chain Component

Data upload can be accomplished using either a POST or a PUT, request depending upon the contract. The contract has full flexibility in implementing endpoints.

Expanding upon the previous example, we can send a POST request with the content "Hello World":

curl --data "Hello world!" https://example.org/executioncontainer/010123456789ABCDEF0123456789ABCDEF01234567/upload

The recipient contract's off-chain defines the format of the request and response. This example assumes a contract without authentication. If the contract is authenticated you will possibly need to include a header that performs the autentication.

Example: Locating Engines from Contract State

Most contracts will want to specify the endpoints of the associated Execution Engines in the contract state, to make these easily available to clients, though this is not strictly needed, if clients know the endpoints by some other method. When engines are stored in the state, this information can be downloaded, and used to determine the relevant Off-Chain Component endpoints.

At this point the flow would become:

  1. Download list of engines from the contract state, and cache the list, as it is unlikely to cache often (depending upon use case.)
  2. Select relevant engines (possibly them all) from the given list.
  3. Send HTTP requests to the relevant engines.
sequenceDiagram participant User as 👨 User 👩 participant Client as Contract Client participant OnChain as Smart Contract<br>(Reader Node) participant OffChain as Smart Contract Off-Chain<br>(Execution Engine) User ->>+ Client: Call Client ->>+ OnChain: Get State OnChain -->>- Client: State Client ->> Client: Extract HTTP Endpoints<br>for Engines Client ->>+ OffChain: HTTP Request OffChain -->>- Client: HTTP Response Client -->>- User: Response

Example: Authentication

The Platform Blockchain has built-in signing when sending transactions, which makes authentication system very easy to implement. Execution Engines does not specify a standard authentication system, and it is thus the contract programmer's responsibility to define one.

An especially convenient authentication system would be one based on the the same authentication as The Platform Blockchain: ECDSA over the secp256k1 curve, as it would for the user to use the same identity both on-chain and off-chain.

Care must be taken when designing an authentication system for only partially trusted engines. A malicous engine might decide to replay a HTTP request it has received to another node. The authentication system should thus validate that it was the intended recipient of the HTTP request.

This can be done by including the Execution Engine's Address as part of the signed message.

Inspiration for authentication systems can be found in the Secret Sharing Example Contract, which implements a secp256k1 ECDSA-based signature scheme, with the above-mentioned engine validation.

Example: Secret-Sharing

Secure Secret Sharing is the process by which one can split confidential information (plaintext) into pieces such that a person with enough pieces can determine the plaintext, but such that a single piece reveals nothing about the plaintext. The number of pieces needed to reveal the plaintext is configurable, and is often set to be equal to the number of pieces in total.

Secret-sharing is useful for many applications that want to provide confidentiality in a robust manner, and Off-Chain Components are tailor-made for implementing custom secret-sharing protocols.

The simplest secure secret sharing protocol with two pieces is where two byte strings are randomly selected such that the pairwise XOR'ing of the strings are equal to the plaintext.

See the Secret Sharing Example Contract for an example of how to implement an off-chain that provides authenticated secret-sharing. Below figure illustrates the potential flow of the secret sharing upload phase of a secret-sharing contract:

And this figure illustrates the potential flow of the share download and reconstruction phase of a secret-sharing contract: