chaincraft 0.3.2

A high-performance Rust-based platform for blockchain education and prototyping
Documentation
use chaincraft::{
    crypto::ecdsa::{ECDSASigner, ECDSAVerifier},
    error::Result,
    examples::randomness_beacon::{BeaconMessageType, RandomnessBeaconObject},
    network::PeerId,
    storage::MemoryStorage,
    ChaincraftNode,
};
use serde_json::json;
use std::sync::Arc;
use tokio::time::{sleep, Duration};

async fn create_beacon_node() -> ChaincraftNode {
    let id = PeerId::new();
    let storage = Arc::new(MemoryStorage::new());
    let mut node = ChaincraftNode::new(id, storage);
    node.set_port(0); // Use ephemeral port
    node.start().await.unwrap();
    node
}

#[tokio::test]
async fn test_randomness_beacon_setup() {
    let mut node = create_beacon_node().await;

    // Test that randomness beacon can be initialized
    assert!(node.is_running());

    node.close().await.unwrap();
}

#[tokio::test]
async fn test_beacon_round_generation() {
    let mut node = create_beacon_node().await;

    // Test beacon round generation with correct parameters
    let beacon_obj = RandomnessBeaconObject::new(60, 3).unwrap();

    // Test validation logic instead of direct message handling
    assert_eq!(beacon_obj.current_round, 1);
    assert_eq!(beacon_obj.round_duration_secs, 60);
    assert_eq!(beacon_obj.threshold, 3);

    node.close().await.unwrap();
}

#[tokio::test]
async fn test_beacon_signature_verification() {
    let signer = ECDSASigner::new().unwrap();
    let verifier = ECDSAVerifier::new();

    let beacon_data = b"beacon_round_1_randomness";
    let signature = signer.sign(beacon_data).unwrap();
    let public_key_pem = signer.get_public_key_pem().unwrap();

    // Verify beacon signature
    let is_valid = verifier
        .verify(beacon_data, &signature, &public_key_pem)
        .unwrap();
    assert!(is_valid);

    // Test with invalid data
    let invalid_data = b"invalid_beacon_data";
    let is_invalid = verifier
        .verify(invalid_data, &signature, &public_key_pem)
        .unwrap();
    assert!(!is_invalid);
}

#[tokio::test]
async fn test_vrf_randomness_generation() {
    let mut node = create_beacon_node().await;

    // Simulate VRF-based randomness generation
    let vrf_input = "seed_for_round_1";
    let vrf_msg = json!({
        "message_type": "VRF_BEACON",
        "input": vrf_input,
        "proof": "vrf_proof_data",
        "output": "vrf_random_output"
    });

    node.create_shared_message_with_data(vrf_msg).await.unwrap();
    sleep(Duration::from_millis(100)).await;

    // Success is verified by not throwing an exception

    node.close().await.unwrap();
}

#[tokio::test]
async fn test_beacon_threshold_signatures() {
    let mut nodes = Vec::new();

    // Create multiple nodes for threshold signature simulation
    for _ in 0..3 {
        let node = create_beacon_node().await;
        nodes.push(node);
    }

    // Simulate threshold signature contribution from each node
    for (i, node) in nodes.iter_mut().enumerate() {
        let threshold_msg = json!({
            "message_type": "THRESHOLD_SIG",
            "round": 1,
            "node_id": i,
            "partial_signature": format!("partial_sig_{}", i)
        });

        node.create_shared_message_with_data(threshold_msg)
            .await
            .unwrap();
        sleep(Duration::from_millis(50)).await;
    }

    // Close all nodes
    for mut node in nodes {
        node.close().await.unwrap();
    }

    // Success is verified by not throwing an exception
}

#[tokio::test]
async fn test_beacon_round_validation() {
    let mut node = create_beacon_node().await;

    // Test valid beacon round
    let valid_beacon = json!({
        "message_type": "BEACON_VALIDATION",
        "round": 1,
        "previous_randomness": "0x0000",
        "current_randomness": "0x1234",
        "signature": "valid_signature"
    });

    node.create_shared_message_with_data(valid_beacon)
        .await
        .unwrap();
    sleep(Duration::from_millis(100)).await;

    // Test invalid beacon round (missing fields)
    let invalid_beacon = json!({
        "message_type": "BEACON_VALIDATION",
        "round": 2
        // Missing required fields
    });

    // This should not crash the node
    let _result = node.create_shared_message_with_data(invalid_beacon).await;

    node.close().await.unwrap();
}

#[tokio::test]
async fn test_beacon_network_synchronization() {
    let mut node1 = create_beacon_node().await;
    let mut node2 = create_beacon_node().await;

    // Connect nodes - note: simplified for test, actual connection would need proper peer discovery
    // node1.connect_to_peer("127.0.0.1".to_string(), node2.port()).await.unwrap();
    sleep(Duration::from_millis(100)).await;

    // Node1 generates beacon
    let beacon_msg = json!({
        "message_type": "BEACON_SYNC",
        "round": 1,
        "randomness": "synchronized_randomness",
        "timestamp": chrono::Utc::now().to_rfc3339()
    });

    node1
        .create_shared_message_with_data(beacon_msg)
        .await
        .unwrap();
    sleep(Duration::from_millis(200)).await; // Allow propagation

    node1.close().await.unwrap();
    node2.close().await.unwrap();

    // Success is verified by not throwing an exception
}

#[tokio::test]
async fn test_beacon_bias_resistance() {
    let mut node = create_beacon_node().await;

    // Test that beacon generation is resistant to bias attacks
    let bias_attempt = json!({
        "message_type": "BEACON_BIAS_TEST",
        "round": 1,
        "attempted_bias": "0xffffffff", // Attacker trying to influence randomness
        "legitimate_randomness": "0x12345678"
    });

    node.create_shared_message_with_data(bias_attempt)
        .await
        .unwrap();
    sleep(Duration::from_millis(100)).await;

    // Test multiple bias attempts
    for i in 0..5 {
        let bias_msg = json!({
            "message_type": "BIAS_ATTEMPT",
            "round": 2,
            "attempt": i,
            "biased_value": format!("0x{:08x}", i * 0x11111111)
        });

        node.create_shared_message_with_data(bias_msg)
            .await
            .unwrap();
        sleep(Duration::from_millis(20)).await;
    }

    node.close().await.unwrap();

    // Success is verified by not throwing an exception
}

#[tokio::test]
async fn test_beacon_construction() -> Result<()> {
    // Test beacon round generation with proper parameters
    let mut beacon_obj = RandomnessBeaconObject::new(60, 3).unwrap();

    // Create a VRF proof message
    let msg = BeaconMessageType::VrfProof {
        round: 1,
        input: "test_input".to_string(),
        proof: "test_proof".to_string(),
        output: "test_output".to_string(),
        validator: "test_validator".to_string(),
        signature: "test_signature".to_string(),
        timestamp: chrono::Utc::now(),
    };

    // Process the message instead of using handle_message
    beacon_obj.process_vrf_proof(msg.clone())?;

    // Success is verified by not throwing an exception
    Ok(())
}

#[tokio::test]
async fn test_beacon_node_integration() -> Result<()> {
    let mut node = create_beacon_node().await;

    // Create and send a beacon message
    let beacon_msg = json!({
        "type": "BEACON_MSG",
        "data": {
            "msg_type": "SYNC",
            "round": 1,
            "old_beacon": null
        }
    });

    node.create_shared_message_with_data(beacon_msg).await?;

    // Success is verified by not throwing an exception
    node.close().await?;

    Ok(())
}