@covenance/dlc
Version:
Crypto and Bitcoin functions for Covenance DLC implementation
88 lines (77 loc) • 2.85 kB
text/typescript
import { Point, utils, CURVE } from './secp256k1';
import { PrivKey, PubKey, Signature, EventOutcomeHash } from './types';
import { sha256, bytesToHex } from '../utils';
import { mod } from './general';
/**
* Oracle function to create a commitment for an event in the future.
* @param eventOutcomeHashes - Array of event outcome hashes for each potential event outcome
* @param oraclePubKey - Oracle's public key
* @returns Object containing array of event signature points and event nonce
*/
export async function commitToEvent(
eventOutcomeHashes: EventOutcomeHash[],
oraclePubKey: PubKey
): Promise<{ signaturePoints: Point[]; nonce: bigint }> {
// Generate random nonce
const nonce = utils.randomPrivateKey();
const nonceBigInt = BigInt('0x' + bytesToHex(nonce));
// Compute R = kG
const R = Point.fromPrivateKey(nonce);
// Compute signature points for each outcome
const signaturePoints = await Promise.all(eventOutcomeHashes.map(async m_i => {
// Compute H(R||V||m_i)
const hashInput = new Uint8Array([
...R.toRawBytes(true).slice(1),
...oraclePubKey.toRawBytes(true).slice(1),
...m_i
]);
const hash = await sha256(hashInput);
const e = mod(BigInt('0x' + bytesToHex(hash)), CURVE.n);
// Compute S_i = R + H(R||V||m_i)V
return R.add(oraclePubKey.multiply(e));
}));
return { signaturePoints, nonce: nonceBigInt };
}
/**
* Oracle function to attest to an event outcome.
* @param oraclePrivKey - Oracle's private key
* @param nonce - Event nonce
* @param eventOutcomeHash - Hash of the event outcome
* @returns Oracle's signature for the event outcome
*/
export async function attestEventOutcome(
oraclePrivKey: PrivKey,
nonce: bigint,
eventOutcomeHash: EventOutcomeHash
): Promise<Signature> {
// Compute R = kG
const nonceBytes = new Uint8Array(32);
const nonceHex = nonce.toString(16).padStart(64, '0');
for (let i = 0; i < 32; i++) {
nonceBytes[i] = parseInt(nonceHex.slice(i * 2, i * 2 + 2), 16);
}
const R = Point.fromPrivateKey(nonceBytes);
// Get oracle's public key
const V = Point.fromPrivateKey(oraclePrivKey);
// Compute H(R||V||m_i)
const hashInput = new Uint8Array([
...R.toRawBytes(true).slice(1),
...V.toRawBytes(true).slice(1),
...eventOutcomeHash
]);
const hash = await sha256(hashInput);
const e = mod(BigInt('0x' + bytesToHex(hash)), CURVE.n);
// Compute s_i = k + H(R||V||m_i)v
const v = BigInt('0x' + bytesToHex(oraclePrivKey));
const s_i = mod(nonce + e * v, CURVE.n);
return { R, s: s_i };
}
/**
* Function to extract the oracle's private key from two oracle outcome attestations.
* This is to keep the oracle from cheating.
*/
/* c8 ignore start */
export function extractOraclePrivKey(): void {
throw new Error('Not implemented');
}
/* c8 ignore stop */