Skip to content

Commit 0d98939

Browse files
CopilotSteake
andcommitted
Add comprehensive governance system implementation
- Create bitcell-governance crate with full implementation - Implement proposal system (parameter changes, treasury, upgrades) - Implement token-weighted voting (linear and quadratic) - Implement delegation system - Implement type-specific timelock delays - Implement multi-sig guardian controls - Add 20+ comprehensive unit tests - Add integration tests - Add benchmarks - Create documentation (GOVERNANCE.md and README.md) Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
1 parent ae49907 commit 0d98939

12 files changed

Lines changed: 2876 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ members = [
1616
"crates/bitcell-wallet-gui",
1717
"crates/bitcell-compiler",
1818
"crates/bitcell-light-client",
19+
"crates/bitcell-governance",
1920
]
2021
resolver = "2"
2122

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[package]
2+
name = "bitcell-governance"
3+
version.workspace = true
4+
authors.workspace = true
5+
edition.workspace = true
6+
rust-version.workspace = true
7+
license.workspace = true
8+
repository.workspace = true
9+
10+
[dependencies]
11+
bitcell-crypto = { path = "../bitcell-crypto" }
12+
bitcell-state = { path = "../bitcell-state" }
13+
serde.workspace = true
14+
serde_json.workspace = true
15+
thiserror.workspace = true
16+
bincode.workspace = true
17+
tracing.workspace = true
18+
hex.workspace = true
19+
sha2.workspace = true
20+
21+
[dev-dependencies]
22+
proptest.workspace = true
23+
criterion.workspace = true
24+
tempfile = "3.23.0"
25+
26+
[[bench]]
27+
name = "governance_bench"
28+
harness = false
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# BitCell Governance
2+
3+
On-chain governance system for the BitCell blockchain.
4+
5+
## Overview
6+
7+
The governance system enables decentralized decision-making for protocol parameters, treasury spending, and protocol upgrades. It implements token-weighted voting with delegation support and guardian emergency controls.
8+
9+
## Features
10+
11+
- **Proposal System**: Submit and vote on three types of proposals:
12+
- Parameter changes (e.g., max block size, minimum stake)
13+
- Treasury spending (allocate funds from protocol treasury)
14+
- Protocol upgrades (deploy new protocol versions)
15+
16+
- **Voting Methods**:
17+
- Linear voting: 1 CELL = 1 vote
18+
- Quadratic voting: sqrt(CELL) = votes (Sybil-resistant)
19+
20+
- **Delegation**: Delegate your voting power to trusted representatives
21+
22+
- **Timelock Protection**:
23+
- Parameter changes: 2-day delay
24+
- Protocol upgrades: 2-day delay
25+
- Treasury spending: 6-hour delay
26+
27+
- **Guardian Controls**: 2-of-3 multi-sig for emergency actions
28+
- Cancel malicious proposals
29+
- Execute critical upgrades immediately
30+
31+
## Quick Start
32+
33+
```rust
34+
use bitcell_governance::{GovernanceManager, ProposalType, VotingMethod, GuardianSet};
35+
36+
// Create governance manager
37+
let mut gov = GovernanceManager::new();
38+
39+
// Submit a proposal
40+
let proposer = [1u8; 33];
41+
let proposal_id = gov.submit_proposal(
42+
proposer,
43+
ProposalType::ParameterChange {
44+
parameter: "max_block_size".to_string(),
45+
new_value: "2000000".to_string(),
46+
},
47+
"Increase max block size to 2MB".to_string(),
48+
current_timestamp,
49+
)?;
50+
51+
// Vote on the proposal
52+
let voter = [2u8; 33];
53+
let voting_power = 10000 * 100_000_000; // 10,000 CELL
54+
gov.vote(proposal_id, voter, true, voting_power, current_timestamp)?;
55+
56+
// Finalize after timelock expires
57+
let passed = gov.finalize_proposal(proposal_id, current_timestamp + (2 * 24 * 60 * 60))?;
58+
59+
if passed {
60+
println!("Proposal passed!");
61+
}
62+
```
63+
64+
## Delegation
65+
66+
```rust
67+
// Delegate voting power
68+
let delegator = [1u8; 33];
69+
let delegatee = [2u8; 33];
70+
let amount = 5000 * 100_000_000; // 5,000 CELL
71+
72+
gov.delegate(delegator, delegatee, amount)?;
73+
74+
// Delegatee now has additional voting power
75+
let total_power = gov.get_voting_power(&delegatee, base_power);
76+
```
77+
78+
## Guardian Override
79+
80+
```rust
81+
use bitcell_governance::{Guardian, GuardianAction};
82+
83+
// Setup guardians
84+
let guardians = GuardianSet::with_guardians(vec![
85+
Guardian {
86+
pubkey: [1u8; 33],
87+
name: "Guardian 1".to_string(),
88+
added_at: timestamp,
89+
},
90+
Guardian {
91+
pubkey: [2u8; 33],
92+
name: "Guardian 2".to_string(),
93+
added_at: timestamp,
94+
},
95+
Guardian {
96+
pubkey: [3u8; 33],
97+
name: "Guardian 3".to_string(),
98+
added_at: timestamp,
99+
},
100+
]);
101+
102+
// Emergency cancel (requires 2/3 signatures)
103+
let signatures = vec![signature1, signature2]; // 64-byte signatures
104+
gov.guardian_override(proposal_id, GuardianAction::Cancel, signatures)?;
105+
```
106+
107+
## Configuration
108+
109+
```rust
110+
use bitcell_governance::{GovernanceConfig, VotingMethod, GuardianThreshold, TimelockConfig};
111+
112+
let config = GovernanceConfig {
113+
quorum: 10_000 * 100_000_000, // 10,000 CELL minimum
114+
voting_method: VotingMethod::Quadratic,
115+
guardian_threshold: GuardianThreshold {
116+
required: 2,
117+
total: 3,
118+
},
119+
timelock: TimelockConfig {
120+
parameter_change_delay: 2 * 24 * 60 * 60, // 2 days
121+
treasury_spending_delay: 6 * 60 * 60, // 6 hours
122+
protocol_upgrade_delay: 2 * 24 * 60 * 60, // 2 days
123+
},
124+
};
125+
126+
let gov = GovernanceManager::with_config(config, guardians);
127+
```
128+
129+
## Security Features
130+
131+
- **Overflow Protection**: All arithmetic uses saturating operations
132+
- **Collision Resistance**: Proposal IDs use SHA-256 hashing
133+
- **Double-Vote Prevention**: Each address can only vote once per proposal
134+
- **Quadratic Voting**: Reduces influence of large token holders
135+
- **Timelock Delays**: Prevent hasty or malicious changes
136+
- **Guardian Multi-sig**: Emergency response capability
137+
138+
## Testing
139+
140+
```bash
141+
cargo test -p bitcell-governance
142+
```
143+
144+
## Benchmarks
145+
146+
```bash
147+
cargo bench -p bitcell-governance
148+
```
149+
150+
## License
151+
152+
MIT OR Apache-2.0
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2+
use bitcell_governance::*;
3+
4+
const CELL: u64 = 100_000_000;
5+
6+
fn bench_submit_proposal(c: &mut Criterion) {
7+
c.bench_function("submit_proposal", |b| {
8+
let mut gov = GovernanceManager::new();
9+
let mut counter = 0u64;
10+
11+
b.iter(|| {
12+
counter += 1;
13+
gov.submit_proposal(
14+
black_box([1u8; 33]),
15+
black_box(ProposalType::ParameterChange {
16+
parameter: format!("param_{}", counter),
17+
new_value: "value".to_string(),
18+
}),
19+
black_box(format!("Proposal {}", counter)),
20+
black_box(counter),
21+
).unwrap()
22+
});
23+
});
24+
}
25+
26+
fn bench_vote_linear(c: &mut Criterion) {
27+
c.bench_function("vote_linear", |b| {
28+
let mut gov = GovernanceManager::new();
29+
let proposal_id = gov.submit_proposal(
30+
[1u8; 33],
31+
ProposalType::ParameterChange {
32+
parameter: "test".to_string(),
33+
new_value: "value".to_string(),
34+
},
35+
"Test".to_string(),
36+
1000,
37+
).unwrap();
38+
39+
let mut voter_counter = 2u8;
40+
41+
b.iter(|| {
42+
voter_counter = voter_counter.wrapping_add(1);
43+
let voter = [voter_counter; 33];
44+
gov.vote(
45+
black_box(proposal_id),
46+
black_box(voter),
47+
black_box(true),
48+
black_box(1000 * CELL),
49+
black_box(1100),
50+
).unwrap()
51+
});
52+
});
53+
}
54+
55+
fn bench_vote_quadratic(c: &mut Criterion) {
56+
c.bench_function("vote_quadratic", |b| {
57+
let config = GovernanceConfig {
58+
voting_method: VotingMethod::Quadratic,
59+
..Default::default()
60+
};
61+
let mut gov = GovernanceManager::with_config(config, GuardianSet::new());
62+
63+
let proposal_id = gov.submit_proposal(
64+
[1u8; 33],
65+
ProposalType::ParameterChange {
66+
parameter: "test".to_string(),
67+
new_value: "value".to_string(),
68+
},
69+
"Test".to_string(),
70+
1000,
71+
).unwrap();
72+
73+
let mut voter_counter = 2u8;
74+
75+
b.iter(|| {
76+
voter_counter = voter_counter.wrapping_add(1);
77+
let voter = [voter_counter; 33];
78+
gov.vote(
79+
black_box(proposal_id),
80+
black_box(voter),
81+
black_box(true),
82+
black_box(10000 * CELL),
83+
black_box(1100),
84+
).unwrap()
85+
});
86+
});
87+
}
88+
89+
fn bench_delegation(c: &mut Criterion) {
90+
c.bench_function("delegate", |b| {
91+
let mut gov = GovernanceManager::new();
92+
let delegatee = [2u8; 33];
93+
let mut delegator_counter = 3u8;
94+
95+
b.iter(|| {
96+
delegator_counter = delegator_counter.wrapping_add(1);
97+
let delegator = [delegator_counter; 33];
98+
gov.delegate(
99+
black_box(delegator),
100+
black_box(delegatee),
101+
black_box(1000 * CELL),
102+
).unwrap()
103+
});
104+
});
105+
}
106+
107+
fn bench_get_voting_power(c: &mut Criterion) {
108+
c.bench_function("get_voting_power", |b| {
109+
let mut gov = GovernanceManager::new();
110+
let delegatee = [2u8; 33];
111+
112+
// Add some delegations
113+
for i in 0..10 {
114+
gov.delegate([i; 33], delegatee, 1000 * CELL).unwrap();
115+
}
116+
117+
b.iter(|| {
118+
gov.get_voting_power(
119+
black_box(&delegatee),
120+
black_box(5000 * CELL),
121+
)
122+
});
123+
});
124+
}
125+
126+
fn bench_finalize_proposal(c: &mut Criterion) {
127+
c.bench_function("finalize_proposal", |b| {
128+
b.iter_batched(
129+
|| {
130+
let mut gov = GovernanceManager::new();
131+
let proposal_id = gov.submit_proposal(
132+
[1u8; 33],
133+
ProposalType::TreasurySpending {
134+
recipient: [2u8; 33],
135+
amount: 1000 * CELL,
136+
reason: "Test".to_string(),
137+
},
138+
"Test".to_string(),
139+
1000,
140+
).unwrap();
141+
142+
// Vote with quorum
143+
gov.vote(proposal_id, [2u8; 33], true, 15000 * CELL, 1100).unwrap();
144+
145+
(gov, proposal_id)
146+
},
147+
|(mut gov, proposal_id)| {
148+
gov.finalize_proposal(
149+
black_box(proposal_id),
150+
black_box(1000 + 6 * 60 * 60 + 1),
151+
).unwrap()
152+
},
153+
criterion::BatchSize::SmallInput,
154+
);
155+
});
156+
}
157+
158+
fn bench_integer_sqrt(c: &mut Criterion) {
159+
c.bench_function("integer_sqrt", |b| {
160+
b.iter(|| {
161+
// Test with various values
162+
for n in [100, 10000, 1000000, 100000000u64] {
163+
black_box(bitcell_governance::integer_sqrt(n));
164+
}
165+
});
166+
});
167+
}
168+
169+
criterion_group!(
170+
benches,
171+
bench_submit_proposal,
172+
bench_vote_linear,
173+
bench_vote_quadratic,
174+
bench_delegation,
175+
bench_get_voting_power,
176+
bench_finalize_proposal,
177+
bench_integer_sqrt,
178+
);
179+
criterion_main!(benches);

0 commit comments

Comments
 (0)