DLC Oracle

Spec-compliant BIP-340 Schnorr attestations for Discreet Log Contracts. Three event types — enum, numeric, and threshold — with auto-resolution at maturity. Wire format compatible with kormir, dlcdevkit, rust-dlc, and any spec-compliant DLC library.

Overview

The Mycelia Signal DLC Oracle provides cryptographic attestations that enable two parties to construct trustless financial contracts on Bitcoin. The oracle publishes pre-committed nonces in an announcement, then reveals Schnorr signatures at maturity. Those signatures are the only thing that can unlock the on-chain contract — the oracle never touches anyone's money and doesn't know who the counterparties are or how much they bet.

Three event types are supported:

Enum

Disjoint union — 2 to 100 categorical outcomes. Prediction markets, elections, sports, weather categories, coarse price buckets.

Numeric

Digit decomposition — precise value attestation. Configurable base (2-256), digits (1-32), optional sign and scaleFactor for sub-unit precision.

Threshold

Binary outcome — price crosses above or below a strike. Bitcoin-collateralized loans, perpetual hedges.

All event types use BIP-340 Schnorr signatures over secp256k1 with spec-compliant tagged hashes per discreetlogcontracts/dlcspecs. Flat $7.00 USDC / 10,000 sats per event — covers nonce generation, secure storage, and auto-attestation at maturity.

Spec compliance

TLV wire format is byte-for-byte compatible with kormir, dlcdevkit, rust-dlc, bitcoin-s, cfd-dlc, and NDLC. The serialized field in every announcement response is a hex-encoded TLV blob you can feed directly into any spec-compliant DLC library.

Oracle Identity

The DLC oracle runs on a dedicated US instance. The public key is stable and published for independent verification.

PropertyValue
Endpointapi.myceliasignal.com/dlc/
Oracle Pubkey03ff5589b5812f07dec1aad7af189e0513160799820386128a80d37d1503a8e84f
BIP-340 x-onlyff5589b5812f07dec1aad7af189e0513160799820386128a80d37d1503a8e84f

Payment

Two payment rails are supported. Send a request without credentials to receive HTTP 402 with both options — you only need to implement one.

L402 — Lightning (10,000 sats)

Standard L402 protocol. Pay the invoice with any Lightning wallet (Phoenix, Strike, Alby, etc.) and retry with the preimage.

bash
# Step 1 — POST to get the 402 with invoice
curl -s -X POST https://api.myceliasignal.com/dlc/oracle/enum \
  -H "Content-Type: application/json" \
  -d '{"label":"btc-bucket","outcomes":["below_70k","70k_80k","above_80k"],"maturityTs":1780000000}'

# Response: 402 with L402 invoice + x402 payment requirements
# Pay the invoice, then retry with preimage:

curl -s -X POST https://api.myceliasignal.com/dlc/oracle/enum \
  -H "Content-Type: application/json" \
  -H "Authorization: L402 <macaroon>:<preimage>" \
  -d '{"label":"btc-bucket","outcomes":["below_70k","70k_80k","above_80k"],"maturityTs":1780000000}'
Macaroon details

DLC macaroons use URL-safe base64 encoding. Path-bound to the actual endpoint (e.g. /dlc/oracle/enum). Expire in 30 minutes.

x402 — USDC on Base ($7.00)

Standard x402 v2 protocol using EIP-3009 transferWithAuthorization. Sign the transfer from your Base wallet and include the encoded payload.

bash
# Step 1 — POST to get payment requirements
curl -s -X POST https://api.myceliasignal.com/dlc/oracle/enum \
  -H "Content-Type: application/json" \
  -d '{"label":"btc-bucket","outcomes":["below_70k","70k_80k","above_80k"],"maturityTs":1780000000}'

# Response: 402 with payment-required header (x402 v2 requirements)
# Sign EIP-3009 transfer, then retry with PAYMENT-SIGNATURE header:

curl -s -X POST https://api.myceliasignal.com/dlc/oracle/enum \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: <base64-encoded-payload>" \
  -d '{"label":"btc-bucket","outcomes":["below_70k","70k_80k","above_80k"],"maturityTs":1780000000}'
RailAmountNotes
L402 Lightning10,000 sats (~$7)Any Lightning wallet. Macaroon expires in 30 minutes.
x402 USDC$7.00 USDC on BaseEIP-3009 signature. Header: PAYMENT-SIGNATURE. Settlement via Coinbase CDP facilitator.

Endpoints

Enum (disjoint union)

MethodEndpointAuthDescription
POST/dlc/oracle/enumPaidCreate 2-100 outcome event
POST/dlc/oracle/enum/previewFreeDry-run validation, no nonces
GET/dlc/oracle/enumFreeList all enum events
GET/dlc/oracle/enum/{eid}FreeGet announcement JSON
GET/dlc/oracle/enum/{eid}/serializedFreeHex-encoded TLV blob
GET/dlc/oracle/enum/{eid}/attestationFreeGet attestation (404 if pending)

Numeric (digit decomposition)

MethodEndpointAuthDescription
POST/dlc/oracle/numericPaidCreate digit decomposition event
POST/dlc/oracle/numeric/previewFreeDry-run validation, no nonces
GET/dlc/oracle/numericFreeList all numeric events
GET/dlc/oracle/numeric/{eid}FreeGet announcement JSON
GET/dlc/oracle/numeric/{eid}/serializedFreeHex-encoded TLV blob
GET/dlc/oracle/numeric/{eid}/attestationFreeGet per-digit attestation (404 if pending)

Threshold (legacy)

MethodEndpointAuthDescription
POST/dlc/oracle/thresholdPaidRegister threshold contract
DELETE/dlc/oracle/threshold/{eid}PaidCancel contract, attest safe
GET/dlc/oracle/thresholdFreeList active threshold contracts

Discovery (free)

EndpointDescription
GET /dlc/oracle/pubkeyOracle public key, key format, curve, instance identifier
GET /dlc/oracle/statusAnnouncement counts, supported pairs, instance
GET /dlc/oracle/announcementsAll announcements (all types)
GET /dlc/oracle/announcements/{eventid}Single announcement by event ID
GET /dlc/oracle/attestations/{eventid}Attestation. HTTP 425 if not yet attested.

Enum Events — Create and Settle

Enum events are for categorical outcomes where the answer is one bucket from a known set. Customer defines outcomes at creation; oracle publishes one Schnorr signature at maturity revealing the winning outcome.

Create an enum event

bash
curl -s -X POST https://api.myceliasignal.com/dlc/oracle/enum \
  -H "Content-Type: application/json" \
  -H "Authorization: L402 <macaroon>:<preimage>" \
  -d '{
    "label": "btc-price-bucket-may1",
    "outcomes": ["below_70k", "70k_75k", "75k_80k", "above_80k"],
    "maturityTs": 1780000000,
    "metadata": {
      "resolverConfig": {
        "kind": "price_buckets",
        "source": "http://localhost:9200/oracle/price/btc/usd",
        "boundaries": [70000, 75000, 80000]
      }
    }
  }'
json — response
{
  "status": "registered",
  "eventid": "enum-btc-price-bucket-may1-2f6704559a1e-1780000000",
  "type": "enum",
  "outcomes": ["below_70k", "70k_75k", "75k_80k", "above_80k"],
  "maturityTs": 1780000000,
  "oraclePubkey": "ff5589b5812f07dec1aad7af189e0513...",
  "rpoints": ["15c5e0fa...", "c5fa8cf5...", "8e016027...", "e28a267a..."],
  "announcementSignature": "52ca48c15de58dd2...",
  "serialized": "d82452ca48c15de5...",
  "rail": "l402",
  "priceUsd": 7.0
}

The serialized field is a hex-encoded TLV blob per dlcspecs — feed it directly into kormir, dlcdevkit, or any spec-compliant DLC library. One rpoint per outcome.

Enum request fields

FieldTypeRequiredDescription
labelstringYesHuman-readable event label
outcomesstring[]Yes2-100 outcomes, max 256 chars each
maturityTsintYesUnix timestamp, 60s to 365 days future
metadata.resolverConfigobjectNoAuto-resolution config (see below)

Numeric Events — Create and Settle

Numeric events decompose a value into individual digits, each attested separately. This allows counterparties to construct CETs covering all possible price outcomes with arbitrary precision.

Create a numeric event

bash
curl -s -X POST https://api.myceliasignal.com/dlc/oracle/numeric \
  -H "Content-Type: application/json" \
  -H "Authorization: L402 <macaroon>:<preimage>" \
  -d '{
    "label": "btc-usd-may1",
    "base": 10,
    "nbDigits": 7,
    "unit": "USD",
    "maturityTs": 1780000000,
    "metadata": {
      "resolverConfig": {
        "kind": "price_source",
        "source": "http://localhost:9200/oracle/price/btc/usd",
        "scaleFactor": 1
      }
    }
  }'

At maturity, BTC at $77,553 decomposes as digits [0, 0, 7, 7, 5, 5, 3] — seven separate Schnorr signatures revealed. Use scaleFactor for sub-unit precision: scaleFactor=100 against ETH at $4,500.42 gives integer 450042, decomposed as [0, 4, 5, 0, 0, 4, 2] — cent-level precision.

Numeric request fields

FieldTypeRequiredDescription
labelstringYesHuman-readable event label
baseintNoNumeral base, 2-256. Default: 10
nbDigitsintNoNumber of digits, 1-32. Default: 7
isSignedboolNoNegative values supported. Default: false
unitstringNoUnit label, max 32 chars. Default: "USD"
maturityTsintYesUnix timestamp, 60s to 365 days future
metadata.resolverConfigobjectNoAuto-resolution config (see below)

Auto-Resolution

Events created with a resolverConfig in metadata self-settle at maturity. The oracle scheduler checks every 60 seconds for events past maturity and resolves them automatically.

Event TypeResolver KindConfigBehavior
Enumprice_bucketssource, boundariesFetches price, finds matching bucket
EnumwebhookurlGETs URL, expects {"winningOutcome":"..."}
Numericprice_sourcesource, scaleFactorFetches price, multiplies by scaleFactor, decomposes digits
NumericwebhookurlGETs URL, expects {"value":<int>}

Events without a resolverConfig can be manually attested via the admin endpoint (POST /dlc/oracle/{enum,numeric}/{eid}/attest with X-Oracle-Secret header).

Threshold Contracts

Threshold contracts monitor a price continuously and attest when the price crosses a defined level. Binary outcome — breached or safe. Use for Bitcoin-collateralized loans, perpetual hedges, or any binary outcome contract.

Register a threshold contract

bash
curl -s -X POST https://api.myceliasignal.com/dlc/oracle/threshold \
  -H "Content-Type: application/json" \
  -H "Authorization: L402 <macaroon>:<preimage>" \
  -d '{
    "pair": "BTCUSD",
    "strike": 90000,
    "direction": "above",
    "expiry": 1780000000,
    "webhookUrl": "https://your-server.com/dlc-webhook"
  }'
FieldTypeRequiredDescription
pairstringYesUppercase concatenated, e.g. BTCUSD
strikefloatYesPrice level to monitor
directionstringYes"above" or "below"
expiryintNoUnix timestamp. Defaults to 1 year.
webhookUrlstringNoOracle POSTs attestation on breach/expiry. 3 retries with backoff.

Supported Pairs

All 17 pairs support threshold contracts. Enum and numeric events can use any pair via resolverConfig, or any custom data source.

BTCUSD
BTCUSDVWAP
BTCEUR
BTCEURVWAP
BTCJPY
ETHUSD
ETHEUR
ETHJPY
SOLUSD
SOLEUR
SOLJPY
XAUUSD
XAUEUR
XAUJPY
XRPUSD
ADAUSD
DOGEUSD

Cryptography

PropertyValue
Curvesecp256k1
Signature schemeBIP-340 Schnorr with tagged hashes
Announcement tagDLC/oracle/announcement/v0
Attestation tagDLC/oracle/attestation/v0
Public key format32-byte BIP-340 x-only (y-coord implicit even)
NoncesFresh per event, x-only normalized. Deleted post-attestation.
Wire formatTLV per dlcspecs/Messaging.md — BigSize, NFC strings, x_point, signature
TLV types55302 (enum), 55306 (numeric), 55330 (event), 55332 (announcement), 55400 (attestation)
Enum attestationSingle signature for winning outcome
Numeric attestationPer-digit signature, one per digit position
Threshold attestationBinary — breached or safe. Single R-point, single s-value.
R correctnessSignature R component always equals pre-committed announcement R — verified by integration test
Critical correctness property

Every Schnorr signature's R component equals the pre-committed nonce R from the announcement. This is what makes the attestation actually unlock on-chain CETs — not just a signed message. If R doesn't match, counterparties' locked BTC can't be spent.

Key stability

The oracle public key is long-lived and published at GET /dlc/oracle/pubkey. Contracts built against this key will settle using attestations from the same instance. See the Public Keys reference for all signing keys.