Discrete Log Contracts (DLC)¶
Overview¶
Discrete Log Contracts (DLC) enable smart contracts on Bitcoin using Oracle signatures and Bitcoin's native scripting capabilities. The Anya Core implementation provides a complete DLC framework for creating, executing, and settling conditional payments.
Features¶
- Oracle-Based Execution: Smart contracts executed based on external data
- Non-Interactive Setup: Minimal communication required between parties
- Privacy-Preserving: Contract terms not visible on the blockchain
- Bitcoin-Native: Uses only Bitcoin script capabilities
- Flexible Outcomes: Support for binary and multi-outcome contracts
Architecture¶
DLC operates through:
- Contract Setup: Parties agree on terms and oracle
- Funding: Bitcoin is locked in a multi-signature address
- Oracle Attestation: Oracle signs the outcome
- Settlement: Funds are distributed based on oracle signature
Configuration¶
use anya_core::layer2::dlc::{DlcConfig, DlcProtocol};
let config = DlcConfig {
network: "mainnet".to_string(),
oracle_endpoints: vec![
"https://oracle1.example.com".to_string(),
"https://oracle2.example.com".to_string(),
],
timeout_hours: 24,
fee_rate_sat_per_vb: 10,
enable_multioracle: true,
contract_timeout_blocks: 144, // ~24 hours
};
let dlc = DlcProtocol::with_config(config);
Usage¶
Contract Creation¶
use anya_core::layer2::{Layer2Protocol, dlc::DlcProtocol};
use anya_core::layer2::dlc::{ContractDescriptor, OracleInfo, Outcome};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let dlc = DlcProtocol::new();
dlc.initialize().await?;
// Define contract outcomes
let outcomes = vec![
Outcome {
id: "alice_wins".to_string(),
payout_alice: 100000, // satoshis
payout_bob: 0,
probability: 0.5,
},
Outcome {
id: "bob_wins".to_string(),
payout_alice: 0,
payout_bob: 100000,
probability: 0.5,
},
];
// Set up oracle information
let oracle_info = OracleInfo {
public_key: "oracle_public_key".to_string(),
endpoint: "https://sports-oracle.com".to_string(),
event_id: "world_cup_final_2025".to_string(),
attestation_time: 1735689600, // Unix timestamp
};
// Create contract descriptor
let contract = ContractDescriptor {
contract_id: "sports_bet_001".to_string(),
oracle_info,
outcomes,
maturity_time: 1735689600,
fee_rate: 10,
};
println!("DLC contract created: {:?}", contract);
Ok(())
}
Contract Execution¶
use anya_core::layer2::Proof;
// Create execution proof with oracle signature
let execution_proof = Proof {
proof_type: "oracle_attestation".to_string(),
data: oracle_signature.to_vec(),
witness: Some(outcome_data),
metadata: std::collections::HashMap::new(),
};
// Execute the contract
let verification_result = dlc.verify_proof(execution_proof).await?;
if verification_result.is_valid {
println!("Contract executed successfully");
} else {
println!("Contract execution failed: {:?}", verification_result.error_message);
}
Asset-Based Contracts¶
use anya_core::layer2::AssetParams;
// Create DLC with asset-based outcomes
let asset_params = AssetParams {
asset_id: "prediction_market_token".to_string(),
name: "Prediction Market Token".to_string(),
symbol: "PMT".to_string(),
precision: 8,
decimals: 8,
total_supply: 1000000,
metadata: "Token for prediction market outcomes".to_string(),
};
let asset_id = dlc.issue_asset(asset_params).await?;
println!("Prediction market asset created: {}", asset_id);
API Reference¶
DlcProtocol¶
The main DLC protocol implementation.
Methods¶
new() -> Self
: Create a new DLC protocol instancewith_config(config: DlcConfig) -> Self
: Create with custom configurationcreate_contract(&self, descriptor: ContractDescriptor) -> Result<Contract, Error>
execute_contract(&self, contract_id: &str, oracle_sig: &OracleSignature) -> Result<ExecutionResult, Error>
- All methods from
Layer2Protocol
trait
DlcConfig¶
Configuration for DLC operations.
Fields¶
network: String
: Bitcoin networkoracle_endpoints: Vec<String>
: Trusted oracle endpointstimeout_hours: u64
: Contract timeout periodfee_rate_sat_per_vb: u64
: Fee rate for transactionsenable_multioracle: bool
: Enable multi-oracle contractscontract_timeout_blocks: u32
: Timeout in Bitcoin blocks
ContractDescriptor¶
Describes a DLC contract.
Fields¶
contract_id: String
: Unique contract identifieroracle_info: OracleInfo
: Oracle configurationoutcomes: Vec<Outcome>
: Possible contract outcomesmaturity_time: u64
: Contract maturity timestampfee_rate: u64
: Transaction fee rate
OracleInfo¶
Oracle configuration for DLC contracts.
Fields¶
public_key: String
: Oracle's public keyendpoint: String
: Oracle API endpointevent_id: String
: Event identifierattestation_time: u64
: Expected attestation time
Outcome¶
Represents a possible contract outcome.
Fields¶
id: String
: Outcome identifierpayout_alice: u64
: Payout amount for Alicepayout_bob: u64
: Payout amount for Bobprobability: f64
: Outcome probability (0.0 to 1.0)
Oracle Integration¶
Oracle Selection¶
// Configure multiple oracles for redundancy
let oracles = vec![
OracleInfo {
public_key: "oracle1_pubkey".to_string(),
endpoint: "https://oracle1.com".to_string(),
event_id: "btc_price_2025".to_string(),
attestation_time: 1735689600,
},
OracleInfo {
public_key: "oracle2_pubkey".to_string(),
endpoint: "https://oracle2.com".to_string(),
event_id: "btc_price_2025".to_string(),
attestation_time: 1735689600,
},
];
Oracle Communication¶
// The DLC implementation handles oracle communication automatically
// Oracles provide signed attestations for contract resolution
Security Considerations¶
Oracle Trust¶
- Oracle Selection: Choose reputable oracles with good track records
- Multi-Oracle Setup: Use multiple oracles to reduce single points of failure
- Oracle Verification: Verify oracle signatures and attestations
Contract Security¶
- Timelock Safety: Set appropriate timeouts for contract resolution
- Fee Management: Account for fee variations in contract design
- Dispute Resolution: Plan for oracle failure scenarios
Key Management¶
- Secure Storage: Store contract keys securely
- Backup Procedures: Backup contract state and keys
- Access Control: Limit access to contract signing keys
Best Practices¶
Contract Design¶
- Clear Outcomes: Define unambiguous contract outcomes
- Fair Payouts: Design equitable payout structures
- Reasonable Timeouts: Set appropriate contract durations
Oracle Management¶
- Oracle Diversity: Use oracles from different providers
- Event Specificity: Choose specific, verifiable events
- Attestation Timing: Plan for oracle response times
Use Cases¶
Binary Prediction Markets¶
// Simple binary outcome contract
let binary_outcomes = vec![
Outcome {
id: "yes".to_string(),
payout_alice: 200000,
payout_bob: 0,
probability: 0.6,
},
Outcome {
id: "no".to_string(),
payout_alice: 0,
payout_bob: 200000,
probability: 0.4,
},
];
Sports Betting¶
// Multi-outcome sports betting contract
let sports_outcomes = vec![
Outcome { id: "team_a_wins".to_string(), payout_alice: 150000, payout_bob: 50000, probability: 0.4 },
Outcome { id: "team_b_wins".to_string(), payout_alice: 50000, payout_bob: 150000, probability: 0.4 },
Outcome { id: "draw".to_string(), payout_alice: 100000, payout_bob: 100000, probability: 0.2 },
];
Financial Derivatives¶
// Price-based derivative contract
let price_outcomes = vec![
Outcome { id: "above_50k".to_string(), payout_alice: 200000, payout_bob: 0, probability: 0.3 },
Outcome { id: "below_50k".to_string(), payout_alice: 0, payout_bob: 200000, probability: 0.7 },
];
Troubleshooting¶
Common Issues¶
- Oracle Connectivity: Verify oracle endpoints are accessible
- Signature Verification: Check oracle signature formats and keys
- Timeout Handling: Ensure proper timeout configuration
Debugging¶
// Enable detailed logging for DLC operations
use log::{info, debug};
debug!("DLC contract created with ID: {}", contract_id);
info!("Oracle attestation received and verified");
Examples¶
Complete DLC Workflow¶
use anya_core::layer2::{Layer2Protocol, dlc::DlcProtocol};
use anya_core::layer2::dlc::{ContractDescriptor, OracleInfo, Outcome};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let dlc = DlcProtocol::new();
dlc.initialize().await?;
dlc.connect().await?;
// Create a simple binary contract
let oracle_info = OracleInfo {
public_key: "oracle_pubkey_hex".to_string(),
endpoint: "https://price-oracle.com".to_string(),
event_id: "btc_usd_price_2025_12_31".to_string(),
attestation_time: 1735689600,
};
let outcomes = vec![
Outcome {
id: "above_100k".to_string(),
payout_alice: 100000,
payout_bob: 0,
probability: 0.5,
},
Outcome {
id: "below_100k".to_string(),
payout_alice: 0,
payout_bob: 100000,
probability: 0.5,
},
];
let contract = ContractDescriptor {
contract_id: "btc_price_bet_2025".to_string(),
oracle_info,
outcomes,
maturity_time: 1735689600,
fee_rate: 10,
};
// Submit contract (this would create the actual DLC)
let contract_data = serde_json::to_vec(&contract)?;
let contract_id = dlc.submit_transaction(&contract_data).await?;
println!("DLC contract submitted: {}", contract_id);
// Check contract status
let status = dlc.check_transaction_status(&contract_id).await?;
println!("Contract status: {:?}", status);
Ok(())
}