613 lines
19 KiB
Markdown
Executable File
613 lines
19 KiB
Markdown
Executable File
# Blockchain Consensus Design - Proof of Uptime with Game Theory
|
|
|
|
## Current State Analysis
|
|
|
|
### How It Works Now (Line 199-201 in Blockchain.js)
|
|
|
|
```javascript
|
|
static start() {
|
|
log("Blockchain process started. New block will be proposed every 10 minutes.");
|
|
setInterval(this.createBlock.bind(this), 10 * 60 * 1000); // Every 10 minutes
|
|
}
|
|
```
|
|
|
|
**Current Flow:**
|
|
1. **Every town independently** creates blocks every 10 minutes
|
|
2. Each town broadcasts its block to peers
|
|
3. **Problem**: No consensus, no merge, each town has different blocks!
|
|
4. **Result**: Network diverges, no single truth
|
|
|
|
**Issues:**
|
|
- ❌ Multiple conflicting blocks every 10 minutes
|
|
- ❌ No leader election
|
|
- ❌ No block validation voting
|
|
- ❌ No chain merge mechanism
|
|
- ❌ Network splits into N separate chains
|
|
|
|
## Proposed Solution: Proof of Uptime + Rotating Leader + Byzantine Fault Tolerance
|
|
|
|
### Core Principles
|
|
|
|
1. **Proof of Uptime (PoU)**: Towns earn validation rights by staying online
|
|
2. **Rotating Leader**: One validator per round, selected by uptime score
|
|
3. **Byzantine Fault Tolerance**: Tolerates up to 33% malicious nodes
|
|
4. **Economic Incentives**: Aligned with human behavior (game theory)
|
|
5. **Sybil Resistance**: High cost to create fake towns
|
|
|
|
## System Architecture
|
|
|
|
### 1. Uptime Tracking
|
|
|
|
Each town tracks its **uptime score** based on:
|
|
- **Availability**: % time online and reachable
|
|
- **Block participation**: % of rounds where town voted
|
|
- **Data quality**: % of valid transactions submitted
|
|
|
|
```javascript
|
|
// Uptime Score Calculation
|
|
uptimeScore = {
|
|
availability: 0.0 - 1.0, // 0% to 100% uptime in last 7 days
|
|
participation: 0.0 - 1.0, // % of consensus rounds participated
|
|
reputation: 0.0 - 1.0, // % of valid blocks/votes submitted
|
|
|
|
totalScore: (availability * 0.5) + (participation * 0.3) + (reputation * 0.2)
|
|
}
|
|
```
|
|
|
|
**Data Structure:**
|
|
```json
|
|
{
|
|
"townId": "farm",
|
|
"uptimeMetrics": {
|
|
"lastSeen": 1705750800000,
|
|
"totalUptime": 604800000, // 7 days in ms
|
|
"availabilityScore": 0.98,
|
|
"participationCount": 985,
|
|
"totalRounds": 1000,
|
|
"participationScore": 0.985,
|
|
"validBlocksSubmitted": 50,
|
|
"totalBlocksSubmitted": 52,
|
|
"reputationScore": 0.96,
|
|
"totalScore": 0.973
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Leader Selection (Weighted Random)
|
|
|
|
**Algorithm: Weighted Random Selection**
|
|
```javascript
|
|
// Select leader based on uptime scores
|
|
function selectLeader(towns, roundNumber) {
|
|
// Filter active towns (seen in last 15 minutes)
|
|
const activeTowns = towns.filter(t =>
|
|
Date.now() - t.uptimeMetrics.lastSeen < 15 * 60 * 1000
|
|
);
|
|
|
|
// Calculate total weight
|
|
const totalWeight = activeTowns.reduce((sum, t) =>
|
|
sum + t.uptimeMetrics.totalScore, 0
|
|
);
|
|
|
|
// Use round number as seed for deterministic selection
|
|
// All towns calculate the same leader!
|
|
const seed = roundNumber;
|
|
const randomValue = seededRandom(seed) * totalWeight;
|
|
|
|
let cumulativeWeight = 0;
|
|
for (const town of activeTowns) {
|
|
cumulativeWeight += town.uptimeMetrics.totalScore;
|
|
if (randomValue <= cumulativeWeight) {
|
|
return town.townId;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Deterministic random (same seed = same result on all nodes)
|
|
function seededRandom(seed) {
|
|
const x = Math.sin(seed) * 10000;
|
|
return x - Math.floor(x);
|
|
}
|
|
```
|
|
|
|
**Why This Works:**
|
|
- ✅ **Deterministic**: All towns calculate same leader
|
|
- ✅ **Fair**: Higher uptime = higher chance to lead
|
|
- ✅ **Sybil resistant**: New towns have 0 uptime, can't dominate
|
|
- ✅ **No communication**: Pure math, no coordination needed
|
|
|
|
### 3. Consensus Round (10-Minute Cycle)
|
|
|
|
#### Phase 1: Transaction Collection (0:00 - 8:00)
|
|
- All towns collect transactions locally
|
|
- Transactions added to pending pool
|
|
|
|
#### Phase 2: Block Proposal (8:00 - 8:30)
|
|
- **Leader** (selected by uptime) creates block proposal
|
|
- Leader aggregates its own transactions
|
|
- Leader broadcasts proposal to all peers
|
|
|
|
#### Phase 3: Validation Vote (8:30 - 9:30)
|
|
- **All towns** verify block proposal:
|
|
- Check transactions are valid
|
|
- Check signatures are correct
|
|
- Check no double-spends
|
|
- Each town votes: APPROVE or REJECT
|
|
- Vote includes their signature
|
|
|
|
#### Phase 4: Finalization (9:30 - 10:00)
|
|
- Leader counts votes
|
|
- If **>66% APPROVE**: Block is finalized
|
|
- Leader broadcasts final block with votes
|
|
- All towns apply transactions and update blockchain
|
|
|
|
```
|
|
Timeline (10 minutes):
|
|
|-------- 8 min --------|--30s--|--60s--|--30s--|
|
|
[Tx Collection] [Proposal][Vote][Final]
|
|
Leader All Leader
|
|
creates vote counts
|
|
```
|
|
|
|
## Implementation
|
|
|
|
### Phase 1: Uptime Heartbeat System
|
|
|
|
```javascript
|
|
class UptimeTracker {
|
|
/**
|
|
* Each town broadcasts heartbeat every 2 minutes
|
|
*/
|
|
static async sendHeartbeat() {
|
|
const heartbeat = {
|
|
townId: process.env.TOWN,
|
|
timestamp: Date.now(),
|
|
blockHeight: blockchain.length,
|
|
pendingTxCount: pendingTransactions.length,
|
|
signature: await this._sign({ townId: process.env.TOWN, timestamp: Date.now() })
|
|
};
|
|
|
|
await Blockchain._broadcast('/heartbeat', heartbeat);
|
|
}
|
|
|
|
/**
|
|
* Receive and store peer heartbeats
|
|
*/
|
|
static async receiveHeartbeat(heartbeat) {
|
|
if (!await this._verifyHeartbeat(heartbeat)) return;
|
|
|
|
const townFile = path.join(DATA_PATH, 'apxtri/blockchain/uptime', `${heartbeat.townId}.json`);
|
|
|
|
let uptimeData = await fs.readJson(townFile).catch(() => ({
|
|
townId: heartbeat.townId,
|
|
firstSeen: Date.now(),
|
|
heartbeats: []
|
|
}));
|
|
|
|
uptimeData.heartbeats.push({
|
|
timestamp: heartbeat.timestamp,
|
|
blockHeight: heartbeat.blockHeight
|
|
});
|
|
|
|
// Keep last 5000 heartbeats (~7 days at 2-minute intervals)
|
|
if (uptimeData.heartbeats.length > 5000) {
|
|
uptimeData.heartbeats = uptimeData.heartbeats.slice(-5000);
|
|
}
|
|
|
|
// Calculate metrics
|
|
uptimeData.metrics = this._calculateUptimeMetrics(uptimeData.heartbeats);
|
|
|
|
await fs.outputJson(townFile, uptimeData);
|
|
}
|
|
|
|
/**
|
|
* Calculate uptime metrics from heartbeat history
|
|
*/
|
|
static _calculateUptimeMetrics(heartbeats) {
|
|
const now = Date.now();
|
|
const sevenDays = 7 * 24 * 60 * 60 * 1000;
|
|
const recentHeartbeats = heartbeats.filter(h => now - h.timestamp < sevenDays);
|
|
|
|
// Expected: 1 heartbeat every 2 minutes = 5040 in 7 days
|
|
const expectedHeartbeats = sevenDays / (2 * 60 * 1000);
|
|
const availabilityScore = Math.min(recentHeartbeats.length / expectedHeartbeats, 1.0);
|
|
|
|
return {
|
|
lastSeen: heartbeats[heartbeats.length - 1]?.timestamp || 0,
|
|
totalHeartbeats: recentHeartbeats.length,
|
|
availabilityScore,
|
|
totalScore: availabilityScore // Can add participation and reputation later
|
|
};
|
|
}
|
|
|
|
static start() {
|
|
// Send heartbeat every 2 minutes
|
|
setInterval(this.sendHeartbeat.bind(this), 2 * 60 * 1000);
|
|
|
|
// Clean old heartbeats daily
|
|
setInterval(this._cleanOldHeartbeats.bind(this), 24 * 60 * 60 * 1000);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Phase 2: Leader-Based Consensus
|
|
|
|
```javascript
|
|
class Consensus {
|
|
/**
|
|
* Main consensus round (runs every 10 minutes)
|
|
*/
|
|
static async runConsensusRound() {
|
|
const roundNumber = Math.floor(Date.now() / (10 * 60 * 1000));
|
|
const currentTown = process.env.TOWN;
|
|
|
|
log(`[Consensus] Starting round #${roundNumber}`);
|
|
|
|
// 1. Determine leader for this round
|
|
const allTowns = await this._getAllTownsWithUptime();
|
|
const leader = this._selectLeader(allTowns, roundNumber);
|
|
|
|
log(`[Consensus] Leader for round #${roundNumber}: ${leader}`);
|
|
|
|
if (leader === currentTown) {
|
|
// I am the leader
|
|
await this._leaderProposeBlock(roundNumber);
|
|
} else {
|
|
// I am a validator
|
|
await this._validatorWaitForProposal(roundNumber, leader);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Leader creates and proposes block
|
|
*/
|
|
static async _leaderProposeBlock(roundNumber) {
|
|
log(`[Consensus] I am the leader. Creating block proposal...`);
|
|
|
|
if (pendingTransactions.length === 0) {
|
|
log(`[Consensus] No transactions. Skipping round.`);
|
|
return;
|
|
}
|
|
|
|
// Collect transactions from all towns (optional: request from peers)
|
|
const block = {
|
|
index: blockchain.length,
|
|
roundNumber,
|
|
timestamp: Date.now(),
|
|
transactions: [...pendingTransactions],
|
|
previousHash: blockchain.length > 0 ? blockchain[blockchain.length - 1].hash : "0".repeat(64),
|
|
proposer: process.env.TOWN,
|
|
votes: []
|
|
};
|
|
|
|
block.hash = Blockchain._calculateHash(block);
|
|
block.signature = await Blockchain._sign(block);
|
|
|
|
// Broadcast proposal
|
|
log(`[Consensus] Broadcasting block proposal #${block.index}`);
|
|
await Blockchain._broadcast('/propose', block);
|
|
|
|
// Wait 60 seconds for votes
|
|
await new Promise(resolve => setTimeout(resolve, 60 * 1000));
|
|
|
|
// Count votes
|
|
const votes = await this._collectVotes(block.hash);
|
|
const totalVotes = votes.length;
|
|
const approveVotes = votes.filter(v => v.vote === 'approve').length;
|
|
const approvalRate = approveVotes / totalVotes;
|
|
|
|
log(`[Consensus] Votes: ${approveVotes}/${totalVotes} (${(approvalRate * 100).toFixed(1)}%)`);
|
|
|
|
// Require 66% approval (Byzantine fault tolerance)
|
|
if (approvalRate >= 0.66) {
|
|
block.votes = votes;
|
|
blockchain.push(block);
|
|
pendingTransactions = [];
|
|
|
|
// Generate APX3 reward for leader
|
|
const APX3 = require('./APX3');
|
|
await APX3.generateBlockReward(block, process.env.TOWN_MAYOR || process.env.TOWN);
|
|
|
|
log(`[Consensus] ✅ Block #${block.index} FINALIZED with ${approveVotes} votes`);
|
|
|
|
// Broadcast final block
|
|
await Blockchain._broadcast('/finalize', block);
|
|
} else {
|
|
log(`[Consensus] ❌ Block REJECTED. Not enough votes (${approvalRate * 100}% < 66%)`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validator receives proposal and votes
|
|
*/
|
|
static async _validatorWaitForProposal(roundNumber, leader) {
|
|
log(`[Consensus] Waiting for proposal from leader ${leader}...`);
|
|
|
|
// Wait up to 90 seconds for proposal
|
|
const startTime = Date.now();
|
|
while (Date.now() - startTime < 90 * 1000) {
|
|
const proposal = await this._checkForProposal(roundNumber);
|
|
|
|
if (proposal) {
|
|
log(`[Consensus] Received proposal. Validating...`);
|
|
const isValid = await this._validateProposal(proposal);
|
|
|
|
const vote = {
|
|
roundNumber,
|
|
blockHash: proposal.hash,
|
|
voter: process.env.TOWN,
|
|
vote: isValid ? 'approve' : 'reject',
|
|
timestamp: Date.now(),
|
|
signature: await Blockchain._sign({
|
|
roundNumber,
|
|
blockHash: proposal.hash,
|
|
vote: isValid ? 'approve' : 'reject'
|
|
})
|
|
};
|
|
|
|
log(`[Consensus] Voting: ${vote.vote.toUpperCase()}`);
|
|
|
|
// Send vote to leader
|
|
const leaderTown = await this._getTownByID(leader);
|
|
const voteUrl = `http://${leaderTown.dns[0]}/apxtri/blockchain/vote`;
|
|
await axios.post(voteUrl, vote).catch(err =>
|
|
log(`Failed to send vote to leader: ${err.message}`)
|
|
);
|
|
|
|
// Wait for finalization
|
|
await this._waitForFinalization(roundNumber);
|
|
return;
|
|
}
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
}
|
|
|
|
log(`[Consensus] Timeout waiting for proposal from ${leader}`);
|
|
}
|
|
|
|
/**
|
|
* Validate block proposal
|
|
*/
|
|
static async _validateProposal(proposal) {
|
|
try {
|
|
// 1. Verify signature
|
|
if (!await Blockchain._verifySignature(proposal)) {
|
|
log(`[Consensus] Invalid signature`);
|
|
return false;
|
|
}
|
|
|
|
// 2. Check transactions are valid
|
|
for (const tx of proposal.transactions) {
|
|
// Check transaction format
|
|
if (!tx.id || !tx.type || !tx.model) {
|
|
log(`[Consensus] Invalid transaction format`);
|
|
return false;
|
|
}
|
|
|
|
// For APX3 transactions, verify balance
|
|
if (tx.model === 'apx3') {
|
|
const APX3 = require('./APX3');
|
|
const balance = await APX3.getBalance(tx.from);
|
|
if (balance < tx.amount) {
|
|
log(`[Consensus] Insufficient balance for APX3 tx`);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. Check no duplicate transactions
|
|
const txIds = new Set();
|
|
for (const tx of proposal.transactions) {
|
|
if (txIds.has(tx.id)) {
|
|
log(`[Consensus] Duplicate transaction detected`);
|
|
return false;
|
|
}
|
|
txIds.add(tx.id);
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
log(`[Consensus] Validation error: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Select leader using weighted random based on uptime
|
|
*/
|
|
static _selectLeader(towns, roundNumber) {
|
|
const activeTowns = towns.filter(t =>
|
|
Date.now() - t.uptimeMetrics.lastSeen < 15 * 60 * 1000 &&
|
|
t.uptimeMetrics.totalScore > 0.5 // Minimum 50% uptime to lead
|
|
);
|
|
|
|
if (activeTowns.length === 0) {
|
|
return process.env.TOWN; // Fallback
|
|
}
|
|
|
|
const totalWeight = activeTowns.reduce((sum, t) =>
|
|
sum + t.uptimeMetrics.totalScore, 0
|
|
);
|
|
|
|
// Deterministic selection
|
|
const seed = roundNumber + 12345; // Add constant to avoid predictability
|
|
const x = Math.sin(seed) * 10000;
|
|
const randomValue = (x - Math.floor(x)) * totalWeight;
|
|
|
|
let cumulativeWeight = 0;
|
|
for (const town of activeTowns) {
|
|
cumulativeWeight += town.uptimeMetrics.totalScore;
|
|
if (randomValue <= cumulativeWeight) {
|
|
return town.townId;
|
|
}
|
|
}
|
|
|
|
return activeTowns[0].townId; // Fallback
|
|
}
|
|
|
|
static start() {
|
|
// Start consensus rounds every 10 minutes
|
|
// Offset by 30 seconds to allow transaction collection
|
|
setTimeout(() => {
|
|
this.runConsensusRound();
|
|
setInterval(this.runConsensusRound.bind(this), 10 * 60 * 1000);
|
|
}, 30 * 1000);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Game Theory Analysis
|
|
|
|
### Incentive Structure
|
|
|
|
#### Honest Behavior Rewards
|
|
1. **Block Rewards**: 10 APX3 per validated block (only if >66% approve)
|
|
2. **Reputation Score**: Higher chance to be selected as future leader
|
|
3. **Transaction Fees**: Collect fees from all transactions in block
|
|
4. **Network Trust**: Better uptime = more influence
|
|
|
|
#### Malicious Behavior Costs
|
|
1. **Stake at Risk**: Towns must register with DNS (provable cost)
|
|
2. **Reputation Loss**: Bad blocks reduce uptime score
|
|
3. **Block Rejection**: Lose 10 minutes of potential earnings
|
|
4. **Network Exclusion**: Consistent bad behavior = ignored by peers
|
|
5. **Economic Loss**: Wasted electricity, server costs with no reward
|
|
|
|
### Attack Scenarios & Defenses
|
|
|
|
#### Attack 1: Double-Spend Attack
|
|
**Scenario**: Malicious leader includes double-spend transaction
|
|
|
|
**Defense**:
|
|
- ✅ Validators check transaction validity
|
|
- ✅ >66% reject block
|
|
- ✅ Leader gets 0 reward
|
|
- ✅ Leader's reputation drops
|
|
|
|
**Game Theory**: Cost (lost reward + reputation) > Benefit (failed double-spend)
|
|
|
|
#### Attack 2: Sybil Attack (Fake Towns)
|
|
**Scenario**: Attacker creates 100 fake towns to dominate voting
|
|
|
|
**Defense**:
|
|
- ✅ Each town needs registered DNS (cost: $10-50/domain)
|
|
- ✅ New towns have 0 uptime (0% chance to lead)
|
|
- ✅ Takes 7 days to build uptime score
|
|
- ✅ Heartbeat verification with signatures
|
|
|
|
**Game Theory**: Cost ($1000+ for 100 domains + 7 days) > Benefit (might not work)
|
|
|
|
#### Attack 3: Censorship (Leader Ignores Transactions)
|
|
**Scenario**: Malicious leader excludes specific users' transactions
|
|
|
|
**Defense**:
|
|
- ✅ Validators can see missing transactions (compare with their pool)
|
|
- ✅ Can reject block if suspicious
|
|
- ✅ Next round, different leader includes them
|
|
- ✅ Max delay: 10 minutes
|
|
|
|
**Game Theory**: Cost (block rejection + reputation) > Benefit (temporary delay)
|
|
|
|
#### Attack 4: DDoS on Leader
|
|
**Scenario**: Attacker floods leader to prevent block creation
|
|
|
|
**Defense**:
|
|
- ✅ If no proposal in 90 seconds, round fails gracefully
|
|
- ✅ Next round, different leader (rotating)
|
|
- ✅ Leader changes every 10 minutes
|
|
- ✅ DDoS protection at Caddy level
|
|
|
|
**Game Theory**: Cost (DDoS service) > Benefit (delay 1 round)
|
|
|
|
#### Attack 5: 34% Collusion (Byzantine Attack)
|
|
**Scenario**: 34% of towns collude to approve bad blocks
|
|
|
|
**Defense**:
|
|
- ✅ Requires >66% approval (Byzantine fault tolerance)
|
|
- ✅ Need to compromise 67% of network
|
|
- ✅ High uptime towns harder to compromise (established reputation)
|
|
- ✅ Economic cost very high
|
|
|
|
**Game Theory**:
|
|
- To control 67% of voting power: ~67 high-uptime towns
|
|
- Cost: $670 domains + 7 days + server costs
|
|
- Benefit: Can manipulate blockchain
|
|
- Defense: Social layer - community notices suspicious pattern
|
|
|
|
### Optimal Strategy (Nash Equilibrium)
|
|
|
|
**For Honest Town**:
|
|
1. Maximize uptime → Higher leader selection chance
|
|
2. Validate honestly → Build reputation
|
|
3. Vote correctly → Block gets approved, earn fees
|
|
4. Participate consistently → Compound reputation
|
|
|
|
**For Malicious Town**:
|
|
1. Create bad block → 0 reward (rejected)
|
|
2. Vote dishonestly → Block fails anyway (minority)
|
|
3. Stay offline → 0 uptime, never selected
|
|
4. **Conclusion**: Malicious behavior is not profitable!
|
|
|
|
**Nash Equilibrium**: All towns have incentive to behave honestly.
|
|
|
|
## Comparison with Alternatives
|
|
|
|
| Mechanism | Pros | Cons | Suitability |
|
|
|-----------|------|------|-------------|
|
|
| **Proof of Work (PoW)** | Battle-tested, secure | Wasteful energy, slow | ❌ Overkill for apxtri |
|
|
| **Proof of Stake (PoS)** | Energy efficient | Rich get richer, complex | ⚠️ Requires staking mechanism |
|
|
| **Proof of Authority (PoA)** | Fast, efficient | Centralized, trust-based | ❌ Against decentralization |
|
|
| **Proof of Uptime (PoU)** | Meritocratic, efficient | New mechanism | ✅ Perfect for apxtri! |
|
|
|
|
## Migration Path
|
|
|
|
### Phase 1: Heartbeat System (Week 1)
|
|
- Implement uptime tracking
|
|
- All towns start broadcasting heartbeats
|
|
- Build 7 days of uptime data
|
|
|
|
### Phase 2: Leader Selection (Week 2)
|
|
- Implement deterministic leader selection
|
|
- Test leader rotation logic
|
|
- Verify all towns calculate same leader
|
|
|
|
### Phase 3: Consensus Voting (Week 3)
|
|
- Implement proposal/vote/finalize flow
|
|
- Test with small network (3-5 towns)
|
|
- Verify Byzantine fault tolerance
|
|
|
|
### Phase 4: Full Deployment (Week 4)
|
|
- Deploy to production network
|
|
- Monitor for 2 weeks
|
|
- Tune parameters if needed
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables (.env)
|
|
```bash
|
|
# Consensus Settings
|
|
CONSENSUS_ENABLED=true
|
|
BLOCK_TIME=600000 # 10 minutes
|
|
HEARTBEAT_INTERVAL=120000 # 2 minutes
|
|
MIN_UPTIME_TO_LEAD=0.5 # 50% minimum
|
|
VOTE_THRESHOLD=0.66 # 66% approval needed
|
|
PROPOSAL_TIMEOUT=90000 # 90 seconds
|
|
VOTE_COLLECTION_TIME=60000 # 60 seconds
|
|
```
|
|
|
|
## Summary
|
|
|
|
**Proof of Uptime + Rotating Leader** is ideal for apxtri because:
|
|
|
|
✅ **Merit-Based**: Towns that stay online get rewarded
|
|
✅ **Sybil Resistant**: New towns can't instantly dominate
|
|
✅ **Energy Efficient**: No wasteful mining
|
|
✅ **Fast**: 10-minute blocks with 90-second finalization
|
|
✅ **Byzantine Tolerant**: Works with 33% malicious nodes
|
|
✅ **Economically Sound**: Honest behavior is most profitable
|
|
✅ **Decentralized**: No single point of failure
|
|
✅ **Human-Aligned**: Rewards reliability and good citizenship
|
|
|
|
**Game Theory Conclusion**:
|
|
The system creates a **positive-sum game** where cooperation benefits everyone more than defection. The optimal strategy is to be an honest, reliable validator.
|