Files
bft-crdt-experiment/docs/use-case-2-oracle-networks.md

388 lines
11 KiB
Markdown
Raw Permalink Normal View History

# Use Case 2: Decentralized Oracle Networks Without Consensus
## The Oracle Problem
Blockchain smart contracts need external data but face a fundamental dilemma:
### Current Oracle Challenges
1. **Consensus Overhead**
- Chainlink nodes must reach consensus on each price update
- Requires multiple rounds of communication
- Gas costs scale with number of oracles
- Updates limited by consensus frequency
2. **Single Point of Manipulation**
- Consensus produces ONE "official" price
- Attackers know exactly what to target
- Flash loan attacks can manipulate prices
- Time-based attacks exploit update delays
3. **Economic Inefficiency**
- Oracles paid per consensus round
- Can't update continuously due to costs
- Trade-off between security (more oracles) and cost
- Subsidies required for less popular feeds
## The BFT-CRDT Oracle Solution
Instead of consensus, use eventual consistency with on-chain aggregation:
```
Traditional Oracle Network:
[Data Sources] → [Oracle Nodes] → [Consensus Protocol] → [Single Price] → [Smart Contract]
↓ ↓
[Expensive] [Attack Target]
BFT-CRDT Oracle Network:
[Data Sources] → [Oracle Nodes] → [BFT-CRDT Network] → [All Prices] → [Smart Contract]
↓ ↓ ↓ ↓
[Independent] [No consensus] [Time-windowed] [Aggregates]
```
### Key Innovation: Consensus-Free Price Discovery
- Oracles submit prices independently whenever they want
- No coordination or communication between oracles
- Smart contracts see ALL prices within a time window
- Aggregation happens on-chain with custom logic
## Detailed Architecture
### Data Flow
```rust
// 1. Oracle observes price from data source
let price_observation = PriceData {
oracle_id: "oracle_1",
asset_pair: "ETH/USD",
price: 2531_47,
confidence: 99,
source: "binance",
observed_at: timestamp,
};
// 2. Oracle creates signed attestation
let attestation = OracleAttestation {
data: price_observation,
merkle_proof: proof_from_source,
signature: oracle.sign(&price_observation),
};
// 3. Submit to BFT-CRDT network (no consensus needed)
crdt_network.submit(attestation);
// 4. Smart contract queries all recent attestations
let prices = crdt_network.get_attestations(
asset_pair: "ETH/USD",
time_window: Duration::from_secs(300), // 5 minutes
);
// 5. Smart contract applies custom aggregation
let final_price = aggregate_with_outlier_detection(prices);
```
### CRDT Structure
```rust
pub struct OracleCRDT {
// All price attestations
attestations: Map<AttestationId, OracleAttestation>,
// Index by asset and time
price_index: BTreeMap<(AssetPair, Timestamp), Vec<AttestationId>>,
// Oracle reputation tracking
oracle_performance: Map<OracleId, PerformanceMetrics>,
// Detected anomalies
anomalies: Set<AnomalyReport>,
}
pub struct OracleAttestation {
pub id: AttestationId,
pub oracle_id: OracleId,
pub asset_pair: AssetPair,
pub price: u128,
pub confidence: u8,
pub sources: Vec<DataSource>,
pub timestamp: Timestamp,
pub proof: SourceProof,
pub signature: Signature,
}
pub struct SourceProof {
// Proof that price came from claimed source
pub source_signature: Option<Signature>,
pub api_attestation: Option<TLSProof>,
pub merkle_path: Option<MerklePath>,
}
```
### Merge Rules
```rust
impl Merge for OracleCRDT {
fn merge(&mut self, other: &Self) {
// 1. Merge attestations (no conflicts possible)
for (id, attestation) in &other.attestations {
if !self.attestations.contains_key(id) {
if self.verify_attestation(attestation) {
self.add_attestation(attestation.clone());
}
}
}
// 2. Update performance metrics
self.update_oracle_performance(&other.oracle_performance);
// 3. Merge anomaly reports
self.anomalies.extend(&other.anomalies);
}
}
```
## Smart Contract Integration
### On-Chain Aggregation
```solidity
contract PriceAggregator {
struct PriceData {
uint128 price;
uint8 confidence;
address oracle;
uint256 timestamp;
}
function getPrice(
string calldata assetPair,
uint256 maxAge
) external view returns (uint128) {
// Get all prices from CRDT oracle network
PriceData[] memory prices = oracleNetwork.getPrices(
assetPair,
block.timestamp - maxAge,
block.timestamp
);
require(prices.length >= MIN_SOURCES, "Insufficient data");
// Apply custom aggregation logic
return calculateWeightedMedian(prices);
}
function calculateWeightedMedian(
PriceData[] memory prices
) internal pure returns (uint128) {
// Sort by price
sortPrices(prices);
// Remove outliers (> 2 std dev)
uint256 validCount = removeOutliers(prices);
// Weight by confidence and recency
uint256[] memory weights = calculateWeights(prices, validCount);
// Find weighted median
return findWeightedMedian(prices, weights, validCount);
}
}
```
### Advanced Aggregation Strategies
```solidity
library OracleAggregation {
// Time-Weighted Average Price (TWAP)
function calculateTWAP(
PriceData[] memory prices,
uint256 duration
) internal pure returns (uint128) {
uint256 weightedSum = 0;
uint256 totalWeight = 0;
for (uint i = 0; i < prices.length; i++) {
uint256 timeWeight = duration - (block.timestamp - prices[i].timestamp);
weightedSum += prices[i].price * timeWeight;
totalWeight += timeWeight;
}
return uint128(weightedSum / totalWeight);
}
// Volatility-Adjusted Price
function getVolAdjustedPrice(
PriceData[] memory prices
) internal pure returns (uint128 price, uint128 confidence) {
uint128 median = getMedian(prices);
uint128 stdDev = getStandardDeviation(prices, median);
// Higher volatility = lower confidence
confidence = stdDev < median / 100 ? 99 : 50;
// Use trimmed mean for volatile periods
if (stdDev > median / 50) {
price = getTrimmedMean(prices, 10); // Trim 10% each side
} else {
price = median;
}
}
}
```
## Security Advantages
### 1. No Single Point of Attack
- No "official" price to manipulate
- Attackers must compromise multiple oracles
- Each oracle failure has limited impact
### 2. Transparent Price Discovery
```solidity
// Anyone can audit all price submissions
function auditPriceHistory(
string calldata assetPair,
uint256 startTime,
uint256 endTime
) external view returns (PriceData[] memory) {
return oracleNetwork.getAllPrices(assetPair, startTime, endTime);
}
```
### 3. Economic Attack Resistance
- No consensus rounds to game
- Continuous submissions prevent timing attacks
- Outlier detection catches manipulated prices
### 4. Oracle Reputation System
```rust
pub struct OracleReputation {
pub total_submissions: u64,
pub accuracy_score: u8, // 0-100
pub average_deviation: u128,
pub downtime_periods: Vec<(Timestamp, Timestamp)>,
pub suspicious_patterns: Vec<SuspiciousPattern>,
}
impl OracleCRDT {
fn update_reputation(&mut self, oracle_id: &OracleId) {
let submissions = self.get_oracle_submissions(oracle_id);
let market_prices = self.calculate_market_consensus(submissions);
// Track how often oracle deviates from market
let deviation = calculate_average_deviation(submissions, market_prices);
// Detect suspicious patterns
let patterns = detect_patterns(submissions);
self.oracle_performance.get_mut(oracle_id).unwrap().update(
deviation,
patterns,
);
}
}
```
## Use Cases
### 1. DeFi Lending Protocols
```solidity
contract LendingProtocol {
function getCollateralValue(
address asset,
uint256 amount
) public view returns (uint256) {
// Get prices from last 5 minutes
uint128 price = priceAggregator.getPrice(
getAssetPair(asset),
300 // 5 minutes
);
// Use conservative estimate for collateral
return (amount * price * 80) / 100; // 80% of market price
}
}
```
### 2. Derivatives and Options
```solidity
contract OptionsProtocol {
function getSettlementPrice(
string calldata assetPair,
uint256 expiryTime
) external view returns (uint128) {
// Get all prices within 1 hour of expiry
PriceData[] memory prices = oracleNetwork.getPrices(
assetPair,
expiryTime - 1800, // 30 min before
expiryTime + 1800 // 30 min after
);
// Use TWAP for fair settlement
return calculateTWAP(prices, 3600);
}
}
```
### 3. Stablecoin Protocols
```solidity
contract StablecoinProtocol {
function getMintPrice() public view returns (uint128) {
// Aggregate multiple fiat sources
uint128 usdPrice = getAggregatePrice("USD", 600);
uint128 eurPrice = getAggregatePrice("EUR", 600);
uint128 gbpPrice = getAggregatePrice("GBP", 600);
// Weight by liquidity
return (usdPrice * 60 + eurPrice * 30 + gbpPrice * 10) / 100;
}
}
```
### 4. Cross-Chain Price Feeds
```rust
// Relay prices to multiple chains without consensus
impl OracleCRDT {
fn relay_to_chain(&self, chain_id: ChainId, asset_pair: AssetPair) {
let prices = self.get_recent_prices(asset_pair, Duration::from_secs(300));
let message = CrossChainPriceUpdate {
prices: prices,
merkle_root: self.calculate_merkle_root(&prices),
timestamp: now(),
};
// Send via BFT-CRDT cross-chain relay
self.cross_chain_relay.send(chain_id, message);
}
}
```
## Performance Analysis
### Throughput
- **Traditional**: ~0.1 updates/second (limited by consensus)
- **BFT-CRDT**: ~100 updates/second per oracle (no coordination)
### Latency
- **Traditional**: 10-60 seconds (consensus rounds)
- **BFT-CRDT**: <1 second (direct submission)
### Cost Comparison
| System | Cost per Update | Updates per Hour | Monthly Cost |
|--------|----------------|------------------|--------------|
| Chainlink | $5-50 | 60 | $216k-2.16M |
| BFT-CRDT | $0.10 | 3600 | $260k |
*Note: BFT-CRDT has higher total cost but provides 60x more data*
### Data Richness
```
Traditional Oracle (per hour):
- 60 consensus prices
- Single value per update
- No individual oracle data
BFT-CRDT Oracle (per hour):
- 3,600 individual submissions