Skip to main content

Build, Deploy & Register Enclave

The enclave is the core component that fetches prices and signs them. You can use Rust, Node.js, or Python - pick based on your preference.

Build the Enclave Image

The project uses Nix for reproducible builds. This ensures the code running in the cloud matches what you built locally. The nix.sh helper runs Nix inside Docker, so you don't need Nix installed.

From the repo root, run the build for your chosen language and architecture:

# Rust (ARM64 — for c6g/c7g instances)
./nix.sh build-rust-arm64

# Node.js (ARM64)
./nix.sh build-node-arm64

# Python (ARM64)
./nix.sh build-python-arm64

For AMD64 instances (c6a.xlarge), use the corresponding -amd64 variants.

Load the resulting tarball into Docker:

docker load < ./rust-arm64-image.tar.gz

Push to a Registry

Tag and push the image to Docker Hub or another registry:

docker tag sui-price-oracle:rust-reproducible-arm64 <YOUR_REGISTRY>/sui-price-oracle:rust-reproducible-arm64
docker push <YOUR_REGISTRY>/sui-price-oracle:rust-reproducible-arm64

Update docker-compose.yml

Get the image digest:

docker inspect --format='{{index .RepoDigests 0}}' <YOUR_REGISTRY>/sui-price-oracle:rust-reproducible-arm64

Update docker-compose.yml to use the digest instead of a tag:

services:
oracle:
image: <YOUR_REGISTRY>/sui-price-oracle@sha256:abc123...
tip

Using the SHA256 digest pins your enclave to an exact image version, which is recommended for production. However, mutable tags like :latest can also be used if you prefer flexibility over strict version locking. PCR16 is generated based on the docker-compose file contents, so as long as the tag name doesn't change, PCR16 remains the same - even if the underlying image is updated.

Deploy to Oyster

Deploy the enclave using the Oyster CLI:

# Export the private key of the wallet with Sui and USDC used for deployments
export PRIVATE_KEY="suiprivkey......."

# Deploy in ARM64
oyster-cvm deploy \
--wallet-private-key $PRIVATE_KEY \
--docker-compose ./enclave_rust/docker-compose.yml \
--instance-type c6g.xlarge \
--duration-in-minutes 60 \
--deployment sui

# Deploy in AMD64
oyster-cvm deploy \
--wallet-private-key $PRIVATE_KEY \
--docker-compose ./enclave_rust/docker-compose.yml \
--instance-type c6a.xlarge \
--duration-in-minutes 60 \
--deployment sui \
--arch amd64

Save the PUBLIC_IP from the output:

export PUBLIC_IP=<ip-address>

Verify the Enclave

Query the enclave to verify it's running:

# Get attestation document
curl http://$PUBLIC_IP:1301/attestation/hex

# Verify PCR values
oyster-cvm verify --enclave-ip $PUBLIC_IP

Record the PCR values: PCR0, PCR1, PCR2, and PCR16.

Register in the Enclave Registry

The enclave registry is a shared, application-independent contract already deployed on-chain. Use the following registry addresses:

NetworkREGISTRY_PACKAGE_IDREGISTRY_ID
Mainnet0x8df76b79118ffad2bacb55705c84474802ddb3d62199b98db720c5088e161ab80xf67a9392da1749e8442d71eb6139a9dc1c199b88ef3da49385eeda175246d9d0
Testnet0x05cd5a306375c49727fc2f1e667df8bcc1f5b52ad07e850074d330afda9327610x7ebc3f9bc7a0cf0820d241ad767036483b885bbd62636fb9446bb0d99d2ed091

Export the registry addresses for your target network:

export REGISTRY_PACKAGE_ID=0x...
export REGISTRY_ID=0x...

Register the enclave (from the repository root):

Mainnet:

oyster-cvm register \
--enclave-ip $PUBLIC_IP \
--wallet-priv-key $PRIVATE_KEY

Testnet:

sh contracts/script/register_enclave.sh \
$REGISTRY_PACKAGE_ID \
$REGISTRY_ID \
$PUBLIC_IP

This fetches the attestation document from the enclave, verifies it on-chain, and stores the public key along with its PCR values in the registry. Once registered, any application can look up this enclave's PCRs.