Skip to content
Merged
27 changes: 27 additions & 0 deletions lib-blockchain/docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,33 @@ Web4 Architecture:
└─────────────────────────────────────────────────┘
```

## Consensus Architecture

### Adaptive Difficulty Adjustment

The blockchain uses governance-controlled difficulty parameters through `DifficultyConfig`:

- **Configurable Parameters**: Target timespan, adjustment interval, and adjustment factors
- **Default Settings**: 14-day timespan, 2016-block interval, 4x max adjustment (Bitcoin-style)
- **Governance Updates**: Parameters can be modified via DAO proposals using `set_difficulty_config()`
- **Audit Trail**: `last_updated_at_height` tracks parameter changes

```rust
pub struct DifficultyConfig {
pub target_timespan: u64, // Default: 14 days (1,209,600 seconds)
pub adjustment_interval: u64, // Default: 2016 blocks
pub max_decrease_factor: u64, // Default: 4 (difficulty can decrease by 4x max)
pub max_increase_factor: u64, // Default: 4 (difficulty can increase by 4x max)
pub last_updated_at_height: u64,
}
```

**Key Methods:**
- `target_block_time()` - Calculates target seconds per block (default: 600s)
- `clamp_timespan()` - Prevents extreme difficulty changes
- `validate()` - Ensures parameters are within safe ranges
- `adjust_difficulty_with_config()` - Calculates new difficulty using config parameters

## Economic Architecture

### Universal Basic Income System
Expand Down
36 changes: 33 additions & 3 deletions lib-blockchain/src/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::collections::{HashMap, HashSet};
use anyhow::Result;
use serde::{Serialize, Deserialize};
use tracing::{info, warn, error, debug};
use crate::types::{Hash, Difficulty};
use crate::types::{Hash, Difficulty, DifficultyConfig};
use crate::transaction::{Transaction, TransactionInput, TransactionOutput, IdentityTransactionData};
use crate::types::transaction_type::TransactionType;
use crate::block::Block;
Expand Down Expand Up @@ -40,6 +40,8 @@ pub struct Blockchain {
pub height: u64,
/// Current mining difficulty
pub difficulty: Difficulty,
/// Difficulty adjustment configuration (governance-controlled)
pub difficulty_config: DifficultyConfig,
/// Total work done (cumulative difficulty)
pub total_work: u128,
/// UTXO set for transaction validation
Expand Down Expand Up @@ -162,6 +164,7 @@ impl Blockchain {
blocks: vec![genesis_block.clone()],
height: 0,
difficulty: Difficulty::from_bits(crate::INITIAL_DIFFICULTY),
difficulty_config: DifficultyConfig::default(),
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing blockchain serialization test (test_blockchain_serialization) does not verify that the difficulty_config field is properly serialized and deserialized. Adding a blockchain field requires updating the test to verify backward compatibility and proper serialization of the new field, especially since this field is critical for governance and consensus operations.

Copilot uses AI. Check for mistakes.
total_work: 0,
utxo_set: HashMap::new(),
nullifier_set: HashSet::new(),
Expand Down Expand Up @@ -798,8 +801,8 @@ impl Blockchain {
tokio::runtime::Handle::current().block_on(async {
let coord = coordinator.read().await;
let interval = coord.get_difficulty_adjustment_interval().await;
let config = coord.get_difficulty_config().await;
(interval, config.target_timespan)
let target_timespan = coord.get_difficulty_target_timespan().await;
(interval, target_timespan)
})
})
} else {
Expand Down Expand Up @@ -913,6 +916,33 @@ impl Blockchain {
self.height
}

/// Get the current difficulty configuration
pub fn get_difficulty_config(&self) -> &DifficultyConfig {
&self.difficulty_config
}

/// Update the difficulty configuration (for governance updates)
///
/// This method validates the new configuration before applying it.
/// The `last_updated_at_height` field will be set to the current blockchain height.
///
/// # Errors
/// Returns an error if the configuration parameters are invalid.
pub fn set_difficulty_config(&mut self, mut config: DifficultyConfig) -> Result<()> {
config.validate().map_err(|e| anyhow::anyhow!("Invalid difficulty config: {}", e))?;
config.last_updated_at_height = self.height;
info!(
"Updating difficulty config at height {}: target_timespan={}, adjustment_interval={}, max_decrease={}, max_increase={}",
self.height,
config.target_timespan,
config.adjustment_interval,
config.max_difficulty_decrease_factor,
config.max_difficulty_increase_factor
);
self.difficulty_config = config;
Ok(())
}

/// Check if a nullifier has been used
pub fn is_nullifier_used(&self, nullifier: &Hash) -> bool {
self.nullifier_set.contains(nullifier)
Expand Down
12 changes: 11 additions & 1 deletion lib-blockchain/src/integration/consensus_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,21 @@ impl BlockchainConsensusCoordinator {
}

/// Get the current difficulty configuration
///
/// **Note**: This clones the entire DifficultyConfig. For better performance,
/// use specific field getters like `get_difficulty_target_timespan()` when you
/// only need individual fields.
pub async fn get_difficulty_config(&self) -> DifficultyConfig {
let manager = self.difficulty_manager.read().await;
manager.config().clone()
}


/// Get the target timespan for difficulty adjustment without cloning the entire config
pub async fn get_difficulty_target_timespan(&self) -> u64 {
let manager = self.difficulty_manager.read().await;
manager.target_timespan()
}

/// Calculate new difficulty using the consensus-owned algorithm
///
/// This is the entry point for blockchain difficulty adjustment.
Expand Down
Loading
Loading