388 lines
11 KiB
Markdown
388 lines
11 KiB
Markdown
# 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 |