Reviewed Aug 2026
DE
DA-05 · LESSON 01

How the Ducat oracle works

KEY DEFINITIONS

Terms used in this lesson

Oracle
A system that reports outside information, such as a market price, for use by a protocol.
Taproot
A Bitcoin output and spending design that can combine a public-key path with privately committed alternative scripts.
Witness
Signatures, scripts, or other data supplied to satisfy a Bitcoin output’s spending condition.
Guardian
A Ducat policy-checking signer that can authorize or reject defined protocol transactions.
DON
Decentralized Oracle Network: a group of independent Chainlink oracle nodes that retrieve, check, combine, and sign outside data.
CRE
Chainlink Runtime Environment: the orchestration layer in which a workflow can request data, run checks, and coordinate outputs. It is not itself the price source.
Nostr
A signed-event messaging protocol; Ducat can use relays to distribute oracle material without making those relays Bitcoin validators.
Validator
Software or a participant that independently checks state transitions under a system's rules. The exact role depends on the protocol being discussed.
Preimage
The original secret data whose hash equals a previously committed value.
Hash160
SHA-256 followed by RIPEMD-160, producing the 20-byte hash used by several Bitcoin spending conditions.
BTC
The common market ticker for bitcoin.
USD
United States dollar, the reference currency in a BTC/USD price.
Vault
A set of Bitcoin outputs and spending rules that holds collateral and represents the current loan state.
Collateral
An asset pledged against a debt; it can be used to cover the debt if agreed conditions are breached.
Tapscript
The version of Bitcoin Script used by a Taproot script-path spend.
Hashlock
A spending condition that requires revealing data matching a committed hash.
Control block
Proof data showing that a revealed script was committed inside a Taproot output.
Schnorr signature
Bitcoin’s Taproot signature scheme, whose algebra supports compact verification and advanced multi-party signing.

Follow one bitcoin price from a signed Chainlink report, through Ducat's precommitted liquidation threshold, to the exact Taproot witness that Bitcoin verifies.

75 min Difficulty 4/5 Not started

Loading lesson visuals...

01

Learn the idea

The Ducat oracle turns an outside BTC/USD price into a secret and signature that one precommitted Bitcoin vault path can verify. Chainlink supplies a signed price report. Ducat checks that report, commits many possible price outcomes in advance, and reveals the secret for a requested threshold only after a later checked price is below it. Bitcoin never reads the price. It checks the revealed secret and Guardian signature required by the vault.

THE PROBLEM

Bitcoin's rules cannot fetch a dollar price from an outside service. A vault must lock in its price condition before the price moves, then receive the missing secret only if a later checked price crosses that condition.

Each participant has one job: Chainlink signs the price report, Ducat checks it and manages the hidden secrets, a Guardian approves the exact vault transaction, and Bitcoin checks the revealed secret and signature.
Inspect all 7 stagesSolve all 16 boundary failuresDecode the report envelopeComplete both commitment checksDistinguish compromised keysOpen exact implementation
THE WHOLE JOURNEY IN ONE MINUTE

Seven handoffs, each with a different job

Start with this plain-language map. The precise names, evidence, and cryptography come later.

  1. 1
    Chainlink packages the priceA signed package states the BTC/USD price, which feed it belongs to, and when it was observed.
  2. 2
    Ducat checks the packageThe workflow accepts a price only when the expected feed, time, and enough authorized signatures pass.
  3. 3
    Ducat prepares many trigger pricesIt publishes the complete set before telling wallets that the new set is current.
  4. 4
    A vault locks in one triggerThe vault's Bitcoin output commits to a hidden secret for its chosen price and to a Guardian key.
  5. 5
    An authorized caller asks for a checkDucat checks only the requested vault thresholds against a newly verified price.
  6. 6
    A Guardian approves the exact transactionThe Guardian checks the proposed liquidation and signs only the transaction it approves.
  7. 7
    Bitcoin checks the committed spendBitcoin verifies the revealed secret, Guardian signature, and normal transaction rules. Ducat software then checks the new protocol state.
PLAIN LANGUAGE FIRST

The nine ideas you need

Read these once, then follow them through the mechanism below.

Chainlink report

A versioned package containing a BTC/USD value, signed timing fields, a feed identifier, and signature evidence from authorized Chainlink oracle nodes.

CRE workflow

Ducat code executed in the Chainlink Runtime Environment (CRE). It fetches and checks reports, then runs the Ducat publishing or evaluation logic.

Oracle snapshot

One signed Ducat record containing the base price, time, Bitcoin network, oracle public key, and the rate range used to build a threshold ladder.

Threshold ladder

A set of prebuilt price contracts, one for each configured collateral-rate step. The secret for each step is hidden until that step is evaluated as breached.

Atomic promotion

The current snapshot is published only after every ladder chunk succeeds. A partial new ladder never becomes the snapshot wallets are told to use.

Replaceable event

A signed Nostr record whose identifying tags let a newer valid record replace an older one. Nostr transports the record but does not decide its truth.

Preimage

The 32-byte threshold key. Its Hash160 value is committed in the vault. Revealing the key lets Bitcoin satisfy that hash check.

Repo and trim

Ducat liquidation transaction families. Repo can process one or more liquidated vaults; trim handles one target and preserves a canonical continuation output.

Successor output

A new Bitcoin output that represents the permitted post-transaction Ducat state. Bitcoin checks ordinary script and value rules; Ducat validators check the protocol-specific shape.

FOLLOW THE COMPLETE FLOW

From outside data to Bitcoin settlement

Select each stage to inspect what enters, what changes, what is checked, and how it can stop.
1

Chainlink returns a signed report

Chainlink Data Streams and its Decentralized Oracle Network (DON)

External data and consensus service
Input
Market data selected and aggregated by the configured Chainlink BTC/USD stream.
What happens
The external Chainlink network produces a Data Streams v3 report and signer evidence. Ducat does not control how the upstream market observations are selected or aggregated.
Output
A fullReport containing report context, a versioned report blob, and ECDSA signature parts.
What is checked
No Ducat decision is made at this stage. The next stage verifies the feed, price, time, and recovered signer addresses.
If it fails
If Chainlink is unavailable, the Ducat workflow has no new report. Bitcoin state does not change.
1 of 7 stages inspected
WORKED TRACE

Trace one illustrative oracle cycle

These values are deliberately simple examples. Feed identifiers, signature thresholds, freshness windows, ladder spacing, confirmation targets, and deployment settings must come from the active versioned configuration rather than being invented here.

1. Signed reportBTC/USD = 100,000.00; raw price = 100000 x 10^18

CRE accepts it only if the feed matches, at least two distinct configured signers recover correctly, and the signed observation time is within 300 seconds.

2. Snapshotbase_price 100,000; base_stamp 17:00; network testnet4

The minute cycle publishes all 866 ladder contracts before promoting the current snapshot.

3. Vault choiceIllustrative chosen rate 1.50 gives threshold ceil(100,000 x 1.35 / 1.50) = 90,000

The wallet computes the matching commit_hash and commits that contract's thold_hash in the vault leaf.

4. Later reportBTC/USD = 88,000

The new checked price is strictly below this vault's 90,000 threshold. Other ladder entries are irrelevant unless their hashes are also requested.

5. EvaluationRequest contains this vault's thold_hash

The workflow regenerates only this requested secret, verifies its commitment, and publishes its kind 1000 breach event.

6. WitnessGuardian signature, 32-byte threshold key, Tapscript, and control block

The stack now satisfies this vault's committed liquidation leaf.

7. State changeBitcoin spends the old UTXO; Ducat validators check repo or trim outputs

Bitcoin validity and Ducat protocol validity are related but distinct checks.

Failure practice comes after the full flow

Inspect all seven stage cards first. This keeps prediction after explanation.

Required: inspect the exact implementationReport bytes, signature checks, hashes, keys, and operator controls. This material is needed for the explanation question.
INSPECT THE INPUT

What CRE receives from Chainlink

The captured code decodes a Data Streams v3 full report. It does not search arbitrary bytes for a plausible price.

TERMS USED BELOW
Solidity ABI
A byte-layout convention for typed values. The decoder uses declared offsets and lengths instead of guessing where fields are.
int192
A signed integer stored in 192 bits. Signed means it can represent negative values, which this workflow rejects for BTC/USD.
Keccak-256
The 256-bit hash used to reconstruct the digest signed by the Chainlink report signers.
Report context
Three fixed 32-byte words included with the report blob when reconstructing the signed digest.
uint32BE
An unsigned 32-bit integer encoded most-significant byte first. BE means big-endian.
HMAC-SHA256
A keyed hash. Ducat uses the oracle secret and public commit_hash to derive a different threshold key for each contract.
Event kind
A Nostr numeric message type, such as 10000 for the current snapshot, 30000 for a threshold contract, or 1000 for a breach.
Sighash
The exact transaction digest a Bitcoin signature authorizes. Changing a covered transaction field changes this digest.
FieldFormatWhy it matters
reportContext[3]Three 32-byte wordsPart of the digest that each authorized signer attests to.
feedId32 bytesMust exactly equal the configured BTC/USD feed identifier.
validFromTimestampUnsigned 32-bit secondsStates when the report becomes valid under the v3 report format.
observationsTimestampUnsigned 32-bit secondsSigned observation time used for the five-minute freshness check.
nativeFee and linkFeeUnsigned 192-bit integersFee fields included in the signed report blob even though Ducat reads the price for this workflow.
expiresAtUnsigned 32-bit secondsReport expiry field included in the v3 signed payload.
priceSigned 192-bit integer with 18 implied decimalsBTC/USD value. The workflow rejects a non-positive or out-of-range result.
bid and askSigned 192-bit integersAdditional v3 price fields preserved in the report blob. Ducat's captured decoder selects the main price field.
rawRs, rawSs, rawVsECDSA signature partsUsed to recover distinct signer addresses for the report digest.
THE EXACT CHECK
  1. Decode the Solidity ABI envelope and the v3 report at fixed field positions.
  2. Hash the report blob, then hash it with all three report-context words using Keccak-256.
  3. Recover each secp256k1 signer address from its ECDSA signature.
  4. Require distinct recovered addresses, all in the configured signer set, to meet the configured threshold.
  5. Reject a feed mismatch, bad signature, missing observation time, price outside bounds, or more than 300 seconds of timestamp difference.
What this proves

Passing these checks proves that enough configured Chainlink signers attested to this exact report payload.

What it cannot prove

It does not prove that BTC/USD is economically perfect. Chainlink's upstream data selection and aggregation remain an external assumption.

INSPECT A COMPLETE FULLREPORT ENVELOPE

This synthetic teaching envelope contains three report-context words, the complete nine-word v3 report blob, and two r, s, and v signature parts. It is not a live market report, and its dummy signatures do not prove authorization.

fullReport 0x00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002800001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000039289090691a1df986e2e2e96670f6435b9a1f913d2306973842db65a9722000000000000000000000000000000000000000000000000000000006553f100000000000000000000000000000000000000000000000000000000006553f1c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006553f29000000000000000000000000000000000000000000000152d02c7e14af680000000000000000000000000000000000000000000000000152a4ce4323444f8000000000000000000000000000000000000000000000000152fb8ab9061a8080000000000000000000000000000000000000000000000000000000000000000000211111111111111111111111111111111111111111111111111111111111111112222222222222222222222222222222222222222222222222222222222222222000000000000000000000000000000000000000000000000000000000000000233333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444444444444444444444444444
Decoded fieldExample valueDecision
feedId0x00039289...a9722Matches captured testnet4 configuration
observationsTimestamp17:00:00 UTC200 seconds before server time, so within 300-second limit
price100000000000000000000000Divide by 10^18 to obtain 100,000.00
signature arrays2 r words, 2 s words, and v bytes 00 01The envelope contains complete signature parts. These synthetic teaching values are not evidence of authorized signers.
expiresAt17:02:00 UTCSigned field is decoded, but this captured Ducat path does not use it for the stated freshness gate

Counting from word[0], which word must CRE read as the signed int192 BTC/USD price before dividing by 10^18?

BUILD THE COMMITMENT

How one threshold becomes a Bitcoin hashlock

The wallet and oracle independently serialize the same values. Any one-byte difference produces a different commitment and the wallet will not find a matching ladder event.

1
Threshold priceceil(base price x 1.35 / selected rate)

The selected rate is the vault's collateral-value-to-debt bucket at the base price. A rate of 1.50 means the collateral is worth 150 percent of the debt. The captured liquidation ratio of 1.35 means 135 percent. Multiplying the base price by 1.35 and dividing by the selected rate finds the BTC price where the ratio falls to that liquidation boundary. Captured testnet rates run from 1.35 to 10.00. These are Ducat configuration values, not Bitcoin rules.

2
Commitment preimageoracle key || UTF-8 network || uint32BE base price || uint32BE base time || uint32BE threshold price

The field order and integer encoding are fixed by the captured implementation.

3
commit_hashBIP340 tagged hash with tag ducat/price_contract_commit

The tag hash is placed twice before the serialized commitment preimage.

4
threshold keyHMAC-SHA256(oracle secret key, commit_hash)

This 32-byte secret can be regenerated by the oracle without storing every ladder secret.

5
thold_hashHash160(threshold key)

This 20-byte value is included in the vault's liquidation leaf.

6
contract IDBIP340 tagged hash of commit_hash || thold_hash

The tag is ducat/price_contract_id. The oracle signs this ID with Schnorr.

Before breach, the vault contains only thold_hash. After breach, the witness reveals the threshold key and Bitcoin executes OP_HASH160, OP_EQUALVERIFY, then OP_CHECKSIG for the Guardian key.
LIVE COMMITMENT CALCULATOR

Change one input and watch every dependent value change

The secret below is a test-only teaching value. It is not an operational Ducat key.

1. threshold price90000
2. commit_hash921165d9559cdf66632513c565ae6ee0b4b8f2822a094378ddb01edddae6fb9a
3. threshold key, secret until breach6923522c91ac8593739d607fac598515af9490a5d0fcf3b9ab4c480793ae5a10
4. thold_hash, placed in vault leaf36b8d5bfea7bb90faf2a33382941ff4c7f41d56d
5. contract ID, signed by oracleb338008eaadeae09375cf2f95b6eb0d0f9f002f360c31b926f51c1df88fff7ec
If only the network changes, what changes?
DO NOT CONFUSE THE KEYS

Four different powers

Chainlink report signer keys
Held by
Members of the configured Chainlink signer set
Allows
Sign the Data Streams report digest
If compromised
A threshold of compromised authorized signers can authenticate a forged report
Relationship
Distinct from every Ducat and Guardian key
Ducat oracle secret and public key
Held by
The Ducat oracle workflow and its custody system
Allows
Derive threshold keys, sign contract IDs, and sign Nostr oracle events
If compromised
Can forge Ducat oracle state and reveal any derived threshold secret
Relationship
The captured code derives the Nostr public key and HMAC material from the same Ducat private key
Authorized HTTP trigger key
Held by
Operator identity not established by the captured repository
Allows
Authorize adjust, status, quote, and evaluate requests to the CRE HTTP trigger
If compromised
Can choose requested hashes and invoke temporary adjustment controls in the dev workflow
Relationship
An EVM-style authorization key configured separately from the Ducat oracle signing key
Guardian key committed by the vault
Held by
One configured Guardian identity; its private signing topology may be single-party or threshold-based outside this SDK leaf
Allows
Sign the liquidation transaction sighash
If compromised
Can contribute authorization to a bad Ducat transaction but still cannot bypass the Bitcoin hashlock
Relationship
Distinct from Chainlink, oracle, and HTTP trigger keys
KEY COMPROMISE CHECK

Which key can forge a Ducat oracle result?

Assume the attacker does not control Chainlink signers or a Guardian quorum. Which single compromised key could sign a false Ducat oracle event and disclose a derived threshold secret?

OPERATOR CONTROL

A dev operator can temporarily adjust the checked price

In the captured hmac-dev workflow, the same separately configured HTTP authorization key that can call evaluation can submit an adjustment percentage and duration. The workflow writes a signed kind 30078 control event using the Ducat oracle key, reads it before ladder creation or evaluation, and multiplies the checked Chainlink price by 1 + percentage / 100.

  1. The HTTP trigger verifies the configured EVM-style authorized caller.
  2. The request is limited to plus or minus 50 percent and at most five minutes.
  3. The workflow publishes a replaceable control event signed by the Ducat oracle key.
  4. The next cycle or evaluation verifies that event, applies the percentage, and rechecks price bounds.
  5. Clients see the adjusted base price in the signed snapshot, but the snapshot does not itself explain the operator's economic reason for changing it.

This dev control is a material operator power and a trust boundary. The captured repository also contained an alpha-mainnet target in the dev tree, while the audit recommended removing dev controls from mainnet builds.

TRUST BOUNDARIES

Who is trusted for what?

ParticipantResponsibilityDo not assume
Chainlink DONProduce and sign the configured market report.Bitcoin verifies the price or that signatures guarantee perfect market accuracy.
Chainlink CREExecute the configured workflow across its runtime and aggregate workflow-node results.CRE chooses Ducat thresholds or owns the Ducat oracle signing policy.
Ducat oracle operator and signing keyConfigure the feed and signer set, publish a coherent ladder, and release the requested breached secrets on time.Commitments remove operator honesty, configuration, key security, or availability assumptions.
Authorized evaluate callerChoose which one to 500 thold_hash values the HTTP workflow evaluates. The captured repository does not identify the human or service holding this separate key.Every unsafe vault is discovered and requested automatically, or that selective omission is prevented by Bitcoin.
Nostr relaysStore and return signed events. The captured workflow queries contract or breach kinds by h tag and pins the expected oracle author, then rechecks the author and NIP-01 Schnorr signature.Relays decide the price, threshold, Bitcoin validity, or can make altered content pass the oracle signature check.
Ducat clients and validatorsVerify oracle material, build transactions, and reconstruct confirmed protocol state.Their database replaces the confirmed Bitcoin transition.
GuardiansCheck Ducat policy and authorize the exact eligible transaction.A valid preimage alone is sufficient to spend the vault.
Bitcoin full nodesVerify the Taproot proof, script, preimage hash, signature, and transaction rules.Nodes fetch Chainlink data or know what BTC/USD should be.
FACTS THAT CAN CHANGE

Configuration and deployment status

These values must be read from the active versioned system. The lesson marks them instead of inventing permanent protocol constants.

Example configurationCaptured testnet4 Data Streams input

Feed 0x00039289...a9722 on the Chainlink testnet Data Engine. The report uses v3 ABI fields and 18 implied price decimals.

Example configurationCaptured signer policy

Four configured signer addresses, threshold two, and require_report_verification set true. Signer membership can rotate with the Chainlink feed configuration.

Example configurationCaptured cycle and ladder

Every minute at second zero; rates 1.35 through 10.00; step 0.01; liquidation value 1.35; 866 contracts in seven chunks; 30-minute ladder expiry.

Implemented, not proven deployedMerged report verification

Fixed v3 decoding, authorized distinct signer recovery, exact feed matching, and fail-closed verification exist in the captured source.

Implemented, not proven deployedMerged freshness and adjustment controls

Reports over 300 seconds from signed observation time are rejected. Adjustment controls are bounded to plus or minus 50 percent for at most five minutes in this captured code.

Not deployed at captureKnown deployment state

The repository deployment table had empty workflow IDs and explicitly said this version was not running. No lesson should present these fixes as live production behavior without a newer deployment snapshot.

Implementation gap at captureStale current-snapshot policy

The old kind 10000 event remains when a new ladder cycle fails, but these repositories do not establish a universal downstream rejection rule once that snapshot becomes old. A production wallet or operator needs an explicit fail-closed age policy for new vault construction and evaluation. This lesson does not invent one.

Unresolved operational risk at captureOracle key custody warning

The captured repository audit identified exposed historical signing material and required key rotation before real-funds use. The lesson does not treat a source-level signature implementation as proof of safe live key custody.

Not established hereBitcoin confirmation and fee policy

No universal confirmation count is created by this oracle. The active wallet, Guardian, mempool, and deployment policy must supply it.

External implementation gap at captureCandidate discovery and handoff

The captured evaluateQuotes endpoint accepts one to 500 thold_hash values, but the inspected repositories do not identify the service that watches vaults, selects those hashes, holds the authorized HTTP key, or hands released secrets to a liquidator. A deployment must define and monitor that path; this lesson does not invent it.

External system boundaryChainlink upstream price formation

Chainlink documents Data Streams as a signed, pull-based report produced by a decentralized oracle network. Exact data-vendor selection, aggregation parameters, and CRE workflow-node agreement are external Chainlink runtime behavior rather than code captured in the Ducat repositories.

Deployment policy unknownGuardian and operator governance

The SDK leaf commits one Guardian public key. Whether it is one signer or a FROST group, its live quorum, key rotation, emergency policy, and the human authorization policy for dev price adjustment were not established in the captured deployment evidence.

VERSION THIS LESSON DESCRIBES

Captured 3 August 2026 at 12:00 UTC

Ducat oracle workflowcre-hmac bd394c3763b4datastream/datastream.go: datastream.DecodeFullReport, DecodeV3Price, VerifyReportSigners; hmac-dev/price.go: fetchPrice; hmac-dev/handlers.go: unifiedOracleCycle, evaluateQuotes; hmac-dev/relay.go: fetchEventByDTag; hmac-dev/crypto.go: signNostrEvent

Implemented in source; workflow IDs empty and not proven deployed

Ducat vault and liquidation validationprotocol-sdk 96cfbe996f8fcrates/ducat-protocol/src/price_contract.rs: price_contract::new; crates/ducat-protocol/src/vault/output.rs: VaultOutput::to_txout; crates/ducat-protocol/src/script/liquidation.rs: create_liquidation_script; crates/ducat-protocol/src/vault/action/repo/validated.rs: RepoAction::validate; crates/ducat-protocol/src/vault/action/trim/validated.rs: TrimAction::validate

Implemented in source and exercised by regtest code

Chainlink Data Streams and CREv3 report format in captured adapterhttps://docs.chain.link/data-streams and https://docs.chain.link/cre

External service; signer configuration and runtime behavior can rotate

This lesson explains the captured implementation, not an asserted live production deployment. A newer code or deployment snapshot must trigger revalidation.

RECAP

Who receives what, and what do they produce?

Chainlink DON

ReceivesMarket observations

ProducesA signed Data Streams report

CRE report adapter

ReceivesThe fullReport and signer configuration

ProducesA checked BTC/USD value or an error

Ducat oracle cycle

ReceivesChecked price and ladder configuration

ProducesA complete signed snapshot and hidden threshold commitments

Ducat wallet

ReceivesThe current snapshot and matching threshold event

ProducesA vault leaf containing thold_hash and a Guardian key

Ducat evaluation workflow

ReceivesRequested thold_hash values and a new checked price

ProducesSigned breach events with the matching threshold keys

Guardian

ReceivesThe exact repo or trim signing request

ProducesA Schnorr signature or a refusal

Bitcoin and Ducat validators

ReceivesThe final transaction and witness

ProducesA Bitcoin spend, then an accepted or rejected Ducat state transition

Important distinctionA valid Chainlink report is enough to liquidate a Ducat vault.

The report only starts an off-chain process. The workflow must verify it, a vault must already contain the matching commitment, the requested threshold must be evaluated, the secret must be released, a Guardian must sign the exact transaction, and Bitcoin must accept its complete Taproot witness.

02
FINISH LEARNING FIRST

The questions unlock after every required learning activity

Inspect all seven stages, solve all sixteen boundary failures, decode the report envelope, complete both commitment checks, distinguish the compromised key, and open the exact implementation section. Your progress is saved automatically.