governance.rs
1 // Copyright (c) 2025 ALPHA/DELTA Network 2 3 //! Governance integration tests. 4 //! 5 //! Tests the governance flow from DELTA to ALPHA: 6 //! - Governor addition/removal proposals 7 //! - Minting rate updates 8 //! - Emergency actions (pause/resume) 9 //! 10 //! These tests verify the IPC message passing and GCI state management. 11 12 use adnet_ipc::{ 13 Address, GovernanceProposalType, MerkleProof, MerkleProofBuilder, ProofVerifier, ProposalId, 14 ProposalOutcome, StateRoot, 15 }; 16 use adnet_runtime::state_roots::{Chain, StateRootTracker}; 17 use adnet_test_utils::{init_test_logging, TestRuntime, TestRuntimeBuilder}; 18 use std::time::Duration; 19 20 /// Test basic proof verification. 21 #[test] 22 fn test_merkle_proof_verification() { 23 let mut builder = MerkleProofBuilder::new(); 24 25 // Add some leaves 26 let data1 = b"governance proposal 1"; 27 let data2 = b"governance proposal 2"; 28 let data3 = b"governance proposal 3"; 29 let data4 = b"governance proposal 4"; 30 31 builder.add_leaf(data1); 32 builder.add_leaf(data2); 33 builder.add_leaf(data3); 34 builder.add_leaf(data4); 35 36 // Build and verify proof for each leaf 37 for (i, data) in [data1, data2, data3, data4].iter().enumerate() { 38 let (proof, root) = builder.build_proof(i).expect("Failed to build proof"); 39 assert!( 40 ProofVerifier::verify_data(&proof, *data, &root), 41 "Proof verification failed for leaf {}", 42 i 43 ); 44 } 45 } 46 47 /// Test that invalid proofs are rejected. 48 #[test] 49 fn test_invalid_proof_rejected() { 50 let mut builder = MerkleProofBuilder::new(); 51 builder.add_leaf(b"correct data"); 52 53 let (proof, root) = builder.build_proof(0).expect("Failed to build proof"); 54 55 // Try to verify with wrong data 56 assert!( 57 !ProofVerifier::verify_data(&proof, b"wrong data", &root), 58 "Invalid proof should be rejected" 59 ); 60 61 // Try to verify with wrong root 62 let wrong_root = StateRoot([0xFF; 32]); 63 assert!( 64 !ProofVerifier::verify_data(&proof, b"correct data", &wrong_root), 65 "Proof against wrong root should be rejected" 66 ); 67 } 68 69 /// Test state root tracker finality logic. 70 #[test] 71 fn test_state_root_tracker_finality() { 72 let mut tracker = StateRootTracker::new(); 73 74 // Record some state roots 75 for height in 100..110 { 76 let root = StateRoot([height as u8; 32]); 77 tracker.record_root(Chain::Delta, height, root); 78 } 79 80 // Update current height 81 tracker.update_height(Chain::Delta, 109); 82 83 // Finality depth is 3, so blocks 100-106 should be finalized 84 assert!(tracker.is_finalized(Chain::Delta, 100), "Block 100 should be finalized"); 85 assert!(tracker.is_finalized(Chain::Delta, 106), "Block 106 should be finalized"); 86 assert!(!tracker.is_finalized(Chain::Delta, 107), "Block 107 should not be finalized"); 87 assert!(!tracker.is_finalized(Chain::Delta, 109), "Block 109 should not be finalized"); 88 89 // Update height further 90 tracker.update_height(Chain::Delta, 112); 91 92 // Now block 109 should be finalized (112 >= 109 + 3) 93 assert!(tracker.is_finalized(Chain::Delta, 109), "Block 109 should now be finalized"); 94 } 95 96 /// Test state root retrieval. 97 #[test] 98 fn test_state_root_retrieval() { 99 let mut tracker = StateRootTracker::new(); 100 101 // Record roots for both chains 102 let alpha_root = StateRoot([0xAA; 32]); 103 let delta_root = StateRoot([0xDD; 32]); 104 105 tracker.record_root(Chain::Alpha, 100, alpha_root.clone()); 106 tracker.record_root(Chain::Delta, 50, delta_root.clone()); 107 108 // Retrieve and verify 109 assert_eq!(tracker.get_root(Chain::Alpha, 100), Some(&alpha_root)); 110 assert_eq!(tracker.get_root(Chain::Delta, 50), Some(&delta_root)); 111 112 // Cross-check should fail 113 assert_eq!(tracker.get_root(Chain::Alpha, 50), None); 114 assert_eq!(tracker.get_root(Chain::Delta, 100), None); 115 } 116 117 /// Test that the test runtime can start with GCI enabled. 118 #[tokio::test] 119 #[ignore = "Requires full node integration"] 120 async fn test_runtime_with_gci() { 121 init_test_logging(); 122 123 let mut runtime = TestRuntimeBuilder::new() 124 .validators(1) 125 .both_chains() 126 .build() 127 .await 128 .expect("Failed to create test runtime"); 129 130 runtime.start().await.expect("Failed to start runtime"); 131 132 // GCI should be accessible from ALPHA runtime 133 // let alpha = runtime.alpha().expect("ALPHA runtime should be enabled"); 134 // let gci = alpha.gci(); 135 // assert!(gci.is_minting_allowed(), "Minting should be allowed initially"); 136 // assert!(gci.is_cross_chain_allowed(), "Cross-chain should be allowed initially"); 137 138 runtime.shutdown().await.expect("Failed to shutdown runtime"); 139 } 140 141 // ========== Placeholder Tests ========== 142 // These document the intended governance test scenarios for Phase 5. 143 144 /// Test AddGovernor proposal flow. 145 /// 146 /// This test will verify: 147 /// 1. User submits AddGovernor proposal on DELTA (requires 1M DX stake) 148 /// 2. DX holders vote (67% required for critical proposals) 149 /// 3. Voting period ends (7 days) 150 /// 4. Timelock period passes (7 days for critical) 151 /// 5. Proposal is executed on DELTA 152 /// 6. Governance outcome is sent to ALPHA via IPC 153 /// 7. ALPHA verifies Merkle proof 154 /// 8. GCI adds new Governor 155 /// 9. Audit log entry is created 156 #[tokio::test] 157 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 158 async fn test_add_governor_proposal_flow() { 159 init_test_logging(); 160 161 let mut runtime = TestRuntime::three_validators() 162 .await 163 .expect("Failed to create test runtime"); 164 165 runtime.start().await.expect("Failed to start runtime"); 166 167 // 1. Create AddGovernor proposal 168 let new_governor = Address([1u8; 32]); 169 let proposal_type = GovernanceProposalType::AddGovernor { 170 address: new_governor.clone(), 171 name: "Federal Reserve Bank".to_string(), 172 jurisdiction: 840, // USA 173 }; 174 175 // 2. Submit proposal on DELTA 176 // let proposal_id = runtime.submit_delta_proposal(proposal_type, proposer_account).await; 177 178 // 3. Vote to pass (67% required) 179 // for voter in voters_with_dx { 180 // runtime.vote_on_proposal(proposal_id, Vote::Yes, voter).await; 181 // } 182 183 // 4. Wait for voting period 184 // runtime.advance_delta_blocks(VOTING_PERIOD_BLOCKS).await; 185 186 // 5. Wait for timelock (7 days) 187 // runtime.advance_delta_blocks(CRITICAL_TIMELOCK_BLOCKS).await; 188 189 // 6. Execute proposal on DELTA 190 // runtime.execute_proposal(proposal_id).await; 191 192 // 7. Wait for cross-chain sync 193 // runtime.wait_for_cross_chain_sync().await; 194 195 // 8. Verify governor added on ALPHA 196 // let alpha = runtime.alpha().unwrap(); 197 // assert!(alpha.gci().is_active_governor(&new_governor)); 198 199 // 9. Verify audit log 200 // let audit = alpha.gci().get_audit_log().last().unwrap(); 201 // assert!(matches!(audit.action, AuditAction::GovernorAdded { .. })); 202 203 runtime.shutdown().await.expect("Failed to shutdown runtime"); 204 } 205 206 /// Test RemoveGovernor proposal flow. 207 #[tokio::test] 208 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 209 async fn test_remove_governor_proposal_flow() { 210 init_test_logging(); 211 212 // Similar to add_governor but removing an existing governor 213 // 1. First add a governor 214 // 2. Submit RemoveGovernor proposal 215 // 3. Vote to pass (67%) 216 // 4. Wait for timelock 217 // 5. Execute 218 // 6. Verify removed on ALPHA 219 } 220 221 /// Test UpdateMintingRate proposal flow. 222 #[tokio::test] 223 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 224 async fn test_update_minting_rate_proposal_flow() { 225 init_test_logging(); 226 227 // 1. Submit UpdateMintingRate proposal (standard, 50% required) 228 // 2. Vote to pass 229 // 3. Wait for 48-hour timelock 230 // 4. Execute 231 // 5. Verify new rate on ALPHA GCI 232 } 233 234 /// Test emergency PauseMinting flow. 235 #[tokio::test] 236 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 237 async fn test_emergency_pause_minting_flow() { 238 init_test_logging(); 239 240 // 1. Submit Emergency::PauseMinting proposal (critical, 67%) 241 // 2. Vote to pass 242 // 3. Wait for 7-day timelock 243 // 4. Execute 244 // 5. Verify minting paused on ALPHA 245 // 6. Governors should not be able to mint while paused 246 } 247 248 /// Test that failed proposals don't affect ALPHA GCI. 249 #[tokio::test] 250 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 251 async fn test_failed_proposal_not_executed() { 252 init_test_logging(); 253 254 // 1. Submit AddGovernor proposal 255 // 2. Vote to fail (less than 67%) 256 // 3. Finalize proposal as failed 257 // 4. Verify governance outcome sent to ALPHA with Failed status 258 // 5. Verify governor NOT added on ALPHA 259 } 260 261 /// Test invalid merkle proof rejected. 262 #[tokio::test] 263 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 264 async fn test_invalid_merkle_proof_rejected() { 265 init_test_logging(); 266 267 // 1. Create a valid governance outcome 268 // 2. Tamper with the merkle proof 269 // 3. Send to ALPHA 270 // 4. Verify ALPHA rejects the tampered proof 271 // 5. GCI state should remain unchanged 272 } 273 274 /// Test governance with different threshold requirements. 275 /// 276 /// - Critical (67%): AddGovernor, RemoveGovernor, Emergency 277 /// - Standard (50%): UpdateMintingRate, UpdateParameters 278 #[tokio::test] 279 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 280 async fn test_governance_thresholds() { 281 init_test_logging(); 282 283 // 1. Test critical proposal with 50% (should fail threshold) 284 // 2. Test critical proposal with 67% (should pass) 285 // 3. Test standard proposal with 40% (should fail threshold) 286 // 4. Test standard proposal with 50% (should pass) 287 } 288 289 /// Test governance timelock enforcement. 290 /// 291 /// - Critical: 7 day timelock 292 /// - Standard: 48 hour timelock 293 #[tokio::test] 294 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 295 async fn test_governance_timelocks() { 296 init_test_logging(); 297 298 // 1. Submit critical proposal, vote to pass 299 // 2. Try to execute before 7 days (should fail) 300 // 3. Wait 7 days 301 // 4. Execute (should succeed) 302 303 // 5. Submit standard proposal, vote to pass 304 // 6. Try to execute before 48 hours (should fail) 305 // 7. Wait 48 hours 306 // 8. Execute (should succeed) 307 } 308 309 /// Test concurrent governance proposals. 310 #[tokio::test] 311 #[ignore = "Requires full node integration - placeholder for governance flow testing"] 312 async fn test_concurrent_proposals() { 313 init_test_logging(); 314 315 // 1. Submit multiple proposals concurrently 316 // 2. Vote on each 317 // 3. Verify each is processed correctly 318 // 4. Verify audit log has entries for all 319 }