@covenance/dlc
Version:
Crypto and Bitcoin functions for Covenance DLC implementation
152 lines (126 loc) • 5.46 kB
text/typescript
import { Address, PrivateKey, Script, Networks } from '../src/btc';
import { createLiquidationCets, createDlcInitTx, createMaturityCets } from '../src/cet/transactions';
import { OracleEvent, LoanConfig } from '../src/cet/types';
import { Point, utils } from '../src/crypto/secp256k1';
const createLiquidationEvents = async (
config: LoanConfig,
startTime: number = (Date.now() / 1000) | 0,
): Promise<OracleEvent[]> => {
const count = Math.floor(60 * 60 * 24 * 90 / 60 / 10);
const events = new Array<OracleEvent>(count);
const mockSignaturePoints = Array.from({ length: count }, () => Point.fromPrivateKey(utils.randomPrivateKey()));
// Log progress every 10% of events
const progressInterval = Math.max(1, Math.floor(count / 10));
let lastLogged = 0;
for (let i = 0; i < count; i++) {
events[i] = {
id: `event${i}`,
timestamp: startTime + i * 60 * 10,
outcomeSignaturePoints: mockSignaturePoints,
outcomePrices: Array.from({ length: 100 * 10 }, (_, j) => 50000 + j * 100),
};
// Log progress periodically
if (i - lastLogged >= progressInterval) {
const percent = Math.floor((i / count) * 100);
console.log(` ${i}/${count} events created (${percent}%)`);
lastLogged = i;
}
}
return events;
};
async function runBenchmark(): Promise<void> {
console.log('\n--- Starting loan setup ---');
// ---------- KEYSETUP ----------
console.log('• Setting up keys...');
const borrowerKey = new PrivateKey();
const lenderKey = new PrivateKey();
const borrowerAddress = new Address(borrowerKey.toPublicKey(), Networks.testnet, 'witnesspubkeyhash');
const lenderAddress = new Address(lenderKey.toPublicKey(), Networks.testnet, 'witnesspubkeyhash');
// ---------- LOAN CONFIG ----------
console.log('• Configuring loan parameters...');
const borrowedAmountUsd = 15_000; // $15k
const liquidationThreshold = 0.8;
const annualInterestRate = 0.1;
const initialBtcPrice = 100_000; // $100k/BTC
const collateralAmount = (borrowedAmountUsd / initialBtcPrice) * 2; // 200% collateralisation
const config: LoanConfig = {
collateralAmount,
annualInterestRate,
liquidationThreshold,
borrowedAmount: borrowedAmountUsd,
penaltyPercentage: 0.1
};
// ---------- UTXO & DLC INIT ----------
console.log('• Creating DLC initialization transaction...');
const inputAmount = collateralAmount * 2;
const collateralUtxos = [{
txId: 'a'.repeat(64),
outputIndex: 0,
satoshis: inputAmount * 100_000_000,
script: (Script as any).buildWitnessV0Out(borrowerAddress),
}];
const borrowerDlcPrivateKey = utils.randomPrivateKey();
const borrowerDlcPubKey = Point.fromPrivateKey(borrowerDlcPrivateKey);
const lenderDlcPrivateKey = utils.randomPrivateKey();
const lenderDlcPubKey = Point.fromPrivateKey(lenderDlcPrivateKey);
const dlcInitTx = createDlcInitTx(
collateralUtxos,
collateralAmount * 100_000_000,
borrowerDlcPubKey,
lenderDlcPubKey,
borrowerAddress,
);
const dlcUtxo = dlcInitTx.dlcUtxo;
// ---------- ORACLE EVENTS ----------
console.log('\n--- Creating liquidation events ---');
const expectedEvents = Math.floor(60 * 60 * 24 * 90 / 60 / 10);
console.log(`• Will create ${expectedEvents} liquidation events (${60 * 60 * 24 * 90 / 86400} days × ${60 * 10} min intervals)`);
const liquidationEvents = await createLiquidationEvents(config);
console.log('✓ Liquidation events created');
console.log('• Creating maturity event...');
const maturityEvent: OracleEvent = {
id: 'maturity-event',
timestamp: Date.now(),
outcomeSignaturePoints: Array.from({ length: 100 * 10 }, () => Point.fromPrivateKey(utils.randomPrivateKey())),
outcomePrices: Array.from({ length: 100 * 10 }, (_, j) => 50000 + j * 100),
};
// ---------- BENCHMARK ----------
console.log(`\n--- CET creation benchmark ---`);
console.log(`Liquidation events: ${liquidationEvents.length}`);
const t0 = process.hrtime();
const liquidationCets = createLiquidationCets(
liquidationEvents,
config,
dlcUtxo,
borrowerAddress,
lenderAddress,
);
const t1 = process.hrtime();
const maturityCets = createMaturityCets(
maturityEvent,
liquidationEvents[0].timestamp,
config,
dlcUtxo,
borrowerAddress,
lenderAddress,
);
const t2 = process.hrtime();
// ---------- STATISTICS ----------
const nLiquidation = liquidationCets.length;
const nMaturity = maturityCets.length;
const TOTAL_CETS = nLiquidation + nMaturity;
const hrtimeToNs = (t: [number, number]): number => t[0] * 1e9 + t[1];
const nsLiquidation = hrtimeToNs(t1) - hrtimeToNs(t0);
const nsMaturity = hrtimeToNs(t2) - hrtimeToNs(t1);
const nsTotal = hrtimeToNs(t2) - hrtimeToNs(t0);
const fmt = (ns: number): string => `${ns.toFixed(0)}ns`;
const fmtRate = (count: number, ns: number): string => (count / (ns / 1e9)).toFixed(3);
console.log(`\nResults:`);
console.log(` • Liquidation CETs: ${nLiquidation} in ${fmt(nsLiquidation)} → ${fmtRate(nLiquidation, nsLiquidation)} CET/s`);
console.log(` • Maturity CETs: ${nMaturity} in ${fmt(nsMaturity)} → ${fmtRate(nMaturity, nsMaturity)} CET/s`);
console.log(`\nTotal: ${TOTAL_CETS} CETs in ${fmt(nsTotal)} → ${fmtRate(TOTAL_CETS, nsTotal)} CET/s\n`);
}
runBenchmark().catch((err) => {
console.error('Benchmark failed:', err);
process.exit(1);
});