Oracle Implementation Guide

Glittr contracts can require an oracle commitment to verify an off-chain agreement. Oracle commitments can be leveraged in any contract type, and serve as a modifier to that contract. There is a liveness assumption on part of the designated oracle signer, as these commitments are pre-signed and included directly in the Glittr transaction. See the oracle commitment page for more overview.

Oracle Commitments

The data format of the oracle commitment contains the signature (Schnorr) and the oracle message. Represented in typescript format, it looks like this:

type OracleMessageSigned = { // Oracle Commitment
    signature: Vec<u8>,
    message: OracleMessage,
}

The signature is Schnorr signature of sha256(bytes(JSON.stringified(message))).

The oracle message contains the following, which field you need to fill is entirely dependent on the application. The OracleMessage below is a structure of a simple price oracle, e.g. the oracle is saying that 1 BTC = $100,000. The asset_id is optional here for the dApp to verify if the ratio is for the correct currency pair.

type OracleMessage = {
    asset_id: string | null;
    // ratio of 
    ratio: Fraction | null;
    // the bitcoin block height when the message is signed
    block_height: number;
}

type Fraction = (number, number);

Example:

At blockheight 878000 the price of 1 MeowToken is 80 USD. The oracle message is:

{
  "signature": [56, 12, 242, ...],
  "message": {
    "asset_id": "MeowToken-USD",
    "ratio": (1, 80),
    "block_height": 878000
  }
}

The dApp then will wrap the whole message into a part of a valid Glittr transaction and use this for example to mint a MeowToken-collateralized USD.

Example implementation

The example below is written using TypeScript and imports the glittr-sdk package and @noble/secp256k1 for the digital signature. The oracle here informs how much sats (bitcoin) is worth in USD. The glittr contract can use this to create collateralized USD, see the USD Contractexample for more.

USD Contract
import { OracleMessage, OracleMessageSigned } from "@glittr-sdk/sdk/dist/transaction/calltype/types";
import { schnorr, utils, getPublicKey } from "@noble/secp256k1";
import { sha256 } from "bitcoinjs-lib/src/crypto";

const main = async () => {
  // ORACLE
  // Generate a random private key
  const oraclePrivateKey = new Uint8Array([
    155, 112, 1, 86, 197, 238, 25, 119, 90, 109, 241, 199, 214, 248, 145, 209,
    253, 107, 11, 21, 162, 36, 125, 70, 42, 12, 110, 21, 177, 251, 9, 79,
  ]);

  // Get the corresponding public key
  const oraclePubkey = Array.from(getPublicKey(oraclePrivateKey, true)).slice(
    1
  );
  console.log("Oracle public key:", Buffer.from(oraclePubkey).toString("hex"));

  // Bitcoin block height, fetch this from RPC
  const blockHeight = 870000;

  const oracleMessage: OracleMessage = {
    asset_id: "sats-usd",
    ratio: [70000, 1], // 70000 sats = 1 usd
    block_height: blockHeight,
  };

  const signature = await schnorr.sign(
    sha256(Buffer.from(JSON.stringify(oracleMessage), "ascii")).toString("hex"),
    oraclePrivateKey
  );

  const oracleCommitment: OracleMessageSigned = {
    signature: Array.from(signature),
    message: oracleMessage,
  };

  console.log(`Oracle Commitment: ${JSON.stringify(oracleCommitment)}`)
};

main()

Result:

Oracle public key: 261f9b464d547bc49ba6695f6fd18cc39b9387b79ffdb9300604f400b982aa4f
Oracle Commitment: {"signature":[193,127,135,233,152,254,69,153,86,222,123,21,97,235,29,221,166,25,246,150,63,63,25,138,98,233,86,34,40,120,249,37,46,95,80,169,49,68,221,58,56,151,150,194,168,82,199,2,237,208,5,139,128,11,17,97,244,27,98,22,198,210,174,246],"message":{"asset_id":"sats-usd","ratio":[70000,1],"block_height":870000}}

The method to communicate between Oracle and dApp is not standardized, Oracle can for example provide an API or even communicate using other channels. As long as the message and signature are correct, dApp can use the oracle message as price information on glittr.

During contract execution, the glittr contract must specify which oracle public key to trust, so make sure as an Oracle you have published the public key.

Last updated