Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions contracts/cdn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ let quality = Some(StreamingQuality::High);
let endpoint = client.get_delivery_endpoint(&content_id, &user_location, &quality)?;

// Record access for analytics
client.record_access(&content_id, &user_location.unwrap(), &node_id, &1000u64, &50u64)?;
if let Some(user_location) = user_location {
client.record_access(&content_id, &user_location, &node_id, &1000u64, &50u64)?;
}
```

## 📊 Implementation Status
Expand Down Expand Up @@ -346,4 +348,4 @@ The contract emits comprehensive events for:

## 📄 License

This contract is part of the TeachLink educational platform and follows the project's licensing terms.
This contract is part of the TeachLink educational platform and follows the project's licensing terms.
4 changes: 2 additions & 2 deletions contracts/cdn/src/analytics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ impl AnalyticsManager {
.unwrap_or_else(|| Vec::new(env));

for i in 0..active_nodes.len() {
let node_id = active_nodes.get(i).unwrap();
if let Some(node) = nodes.get(node_id) {
let node_id = active_nodes.get(i).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(node_id.clone()) {
if node.region == region && node.is_active {
active_nodes_count += 1;
}
Expand Down
16 changes: 7 additions & 9 deletions contracts/cdn/src/cdn_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ impl CDNManager {

let mut new_active_nodes = Vec::new(env);
for i in 0..active_nodes.len() {
let active_node_id = active_nodes.get(i).unwrap();
let active_node_id = active_nodes.get(i).ok_or(CDNError::StorageError)?;
if active_node_id != node_id {
new_active_nodes.push_back(active_node_id);
}
Expand Down Expand Up @@ -299,7 +299,8 @@ impl CDNManager {
let mut replicas = Vec::new(env);
let replica_count = active_nodes.len().min(3);
for i in 0..replica_count {
replicas.push_back(active_nodes.get(i).unwrap());
let node_id = active_nodes.get(i).ok_or(CDNError::StorageError)?;
replicas.push_back(node_id);
}

// Determine default cache policy based on content type
Expand Down Expand Up @@ -405,7 +406,7 @@ impl CDNManager {
let mut best_score = 0u32;

for i in 0..content_item.replicas.len() {
let replica_node_id = content_item.replicas.get(i).unwrap();
let replica_node_id = content_item.replicas.get(i).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(replica_node_id.clone()) {
if !node.is_active {
continue;
Expand Down Expand Up @@ -434,12 +435,9 @@ impl CDNManager {
let selected_node = best_node.ok_or(CDNError::NoAvailableNodes)?;

// Calculate estimated latency based on region and load
let base_latency = if user_location.is_some()
&& user_location.as_ref().unwrap() == &selected_node.region
{
20 // Same region
} else {
100 // Different region
let base_latency = match user_location {
Some(ref user_loc) if *user_loc == selected_node.region => 20,
_ => 100,
};

let load_latency = (selected_node.current_load * 50) / selected_node.capacity;
Expand Down
5 changes: 4 additions & 1 deletion contracts/cdn/src/cost_optimization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ impl CostOptimizationManager {

// Generate alert if thresholds are exceeded
for i in 0..budget.alert_thresholds.len() {
let threshold = budget.alert_thresholds.get(i).unwrap();
let threshold = budget
.alert_thresholds
.get(i)
.ok_or(CDNError::StorageError)?;
if spend_percentage >= threshold as u64 {
let alert_type = if spend_percentage >= 100 {
"exceeded"
Expand Down
37 changes: 23 additions & 14 deletions contracts/cdn/src/disaster_recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl DisasterRecoveryManager {
.unwrap_or_else(|| Map::new(env));

for i in 0..backup_regions.len() {
let region = backup_regions.get(i).unwrap();
let region = backup_regions.get(i).ok_or(CDNError::StorageError)?;
let mut has_active_node = false;

let active_nodes: Vec<String> = env
Expand All @@ -60,8 +60,8 @@ impl DisasterRecoveryManager {
.unwrap_or_else(|| Vec::new(env));

for j in 0..active_nodes.len() {
let node_id = active_nodes.get(j).unwrap();
if let Some(node) = nodes.get(node_id) {
let node_id = active_nodes.get(j).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(node_id.clone()) {
if node.region == region && node.is_active {
has_active_node = true;
break;
Expand Down Expand Up @@ -120,7 +120,9 @@ impl DisasterRecoveryManager {

// In a real implementation, we would trigger actual backup processes here
// For this contract, we'll mark it as completed immediately
let mut completed_record = backup_records.get(backup_id.clone()).unwrap();
let mut completed_record = backup_records
.get(backup_id.clone())
.ok_or(CDNError::StorageError)?;
completed_record.status = BackupStatus::Completed;
backup_records.set(backup_id.clone(), completed_record);
env.storage()
Expand Down Expand Up @@ -193,8 +195,8 @@ impl DisasterRecoveryManager {

let mut target_node_available = false;
for i in 0..active_nodes.len() {
let node_id = active_nodes.get(i).unwrap();
if let Some(node) = nodes.get(node_id) {
let node_id = active_nodes.get(i).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(node_id.clone()) {
if node.region == target_region && node.is_active {
target_node_available = true;
break;
Expand All @@ -217,8 +219,8 @@ impl DisasterRecoveryManager {
// Check if target region is already in replicas
let mut already_exists = false;
for i in 0..content_item.replicas.len() {
let replica_node_id = content_item.replicas.get(i).unwrap();
if let Some(node) = nodes.get(replica_node_id) {
let replica_node_id = content_item.replicas.get(i).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(replica_node_id.clone()) {
if node.region == target_region {
already_exists = true;
break;
Expand All @@ -229,7 +231,7 @@ impl DisasterRecoveryManager {
if !already_exists {
// Find a node in the target region to add as replica
for i in 0..active_nodes.len() {
let node_id = active_nodes.get(i).unwrap();
let node_id = active_nodes.get(i).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(node_id.clone()) {
if node.region == target_region && node.is_active {
content_item.replicas.push_back(node_id);
Expand Down Expand Up @@ -293,7 +295,7 @@ impl DisasterRecoveryManager {
.unwrap_or_else(|| Map::new(env));

for i in 0..critical_content.len() {
let content_id = critical_content.get(i).unwrap();
let content_id = critical_content.get(i).ok_or(CDNError::StorageError)?;
if !content_items.contains_key(content_id) {
return Err(CDNError::ContentNotFound);
}
Expand Down Expand Up @@ -389,11 +391,14 @@ impl DisasterRecoveryManager {

let mut backup_node_id = String::from_str(env, "");
for i in 0..recovery_plan.backup_regions.len() {
let backup_region = recovery_plan.backup_regions.get(i).unwrap();
let backup_region = recovery_plan
.backup_regions
.get(i)
.ok_or(CDNError::StorageError)?;
if backup_region != failed_region {
// Find an active node in this backup region
for j in 0..active_nodes.len() {
let node_id = active_nodes.get(j).unwrap();
let node_id = active_nodes.get(j).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(node_id.clone()) {
if node.region == backup_region && node.is_active {
backup_node_id = node_id;
Expand Down Expand Up @@ -421,14 +426,18 @@ impl DisasterRecoveryManager {
let mut affected_content = Vec::new(env);

for i in 0..recovery_plan.critical_content.len() {
let content_id = recovery_plan.critical_content.get(i).unwrap();
let content_id = recovery_plan
.critical_content
.get(i)
.ok_or(CDNError::StorageError)?;
if let Some(mut content_item) = content_items.get(content_id.clone()) {
// Remove failed region nodes from replicas and add backup node
let mut new_replicas = Vec::new(env);
let mut needs_backup = true;

for j in 0..content_item.replicas.len() {
let replica_node_id = content_item.replicas.get(j).unwrap();
let replica_node_id =
content_item.replicas.get(j).ok_or(CDNError::StorageError)?;
if let Some(node) = nodes.get(replica_node_id.clone()) {
if node.region != failed_region {
new_replicas.push_back(replica_node_id.clone());
Expand Down
5 changes: 4 additions & 1 deletion contracts/cdn/src/security.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,10 @@ impl SecurityManager {
let mut is_allowed = false;

for i in 0..drm_config.allowed_domains.len() {
let allowed_domain = drm_config.allowed_domains.get(i).unwrap();
let allowed_domain = match drm_config.allowed_domains.get(i) {
Some(domain) => domain,
None => continue,
};
// Simplified location matching - in real implementation,
// this would use proper geolocation and domain matching
if user_location == allowed_domain {
Expand Down
23 changes: 16 additions & 7 deletions contracts/cdn/src/streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,17 +267,21 @@ impl StreamingManager {
// If user has a specific preference, try to honor it
if let Some(preferred_quality) = user_preference {
for i in 0..available_profiles.len() {
let profile = available_profiles.get(i).unwrap();
if profile.quality == preferred_quality {
selected_profiles.push_back(profile);
return selected_profiles;
if let Some(profile) = available_profiles.get(i) {
if profile.quality == preferred_quality {
selected_profiles.push_back(profile);
return selected_profiles;
}
}
}
}

// Select profiles based on network bandwidth
for i in 0..available_profiles.len() {
let profile = available_profiles.get(i).unwrap();
let profile = match available_profiles.get(i) {
Some(profile) => profile,
None => continue,
};
let required_bandwidth = (profile.bitrate as u64) * 1000; // Convert kbps to bps

// Include profile if network can handle it with some buffer
Expand All @@ -289,7 +293,9 @@ impl StreamingManager {

// Always include at least the lowest quality profile
if selected_profiles.is_empty() && !available_profiles.is_empty() {
selected_profiles.push_back(available_profiles.get(0).unwrap());
if let Some(profile) = available_profiles.get(0) {
selected_profiles.push_back(profile);
}
}

selected_profiles
Expand All @@ -305,7 +311,10 @@ impl StreamingManager {

// Generate URLs for each quality profile
for i in 0..profiles.len() {
let profile = profiles.get(i).unwrap();
let profile = match profiles.get(i) {
Some(profile) => profile,
None => continue,
};
let quality_str = match profile.quality {
StreamingQuality::Low => "480p",
StreamingQuality::Medium => "720p",
Expand Down
29 changes: 21 additions & 8 deletions contracts/credential_registry/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![no_std]

use soroban_sdk::{
contract, contractevent, contractimpl, symbol_short, Address, Bytes, BytesN, Env,
contract, contracterror, contractevent, contractimpl, symbol_short, Address, Bytes, BytesN, Env,
};

#[contractevent]
Expand All @@ -24,6 +24,14 @@ pub struct Credrev {
#[contract]
pub struct CredentialRegistryContract;

#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum CredentialRegistryError {
CredentialAlreadyExists = 1,
CredentialNotFound = 2,
Unauthorized = 3,
}

#[derive(Clone)]
pub enum CredentialStatus {
Active,
Expand All @@ -43,13 +51,12 @@ impl CredentialRegistryContract {
subject_did: Bytes,
metadata_ptr: Bytes,
expires_at: i128,
) {
) -> Result<(), CredentialRegistryError> {
issuer.require_auth();
let key = (symbol_short!("cred"), credential_hash.clone());
assert!(
!env.storage().persistent().has(&key),
"credential already exists"
);
if env.storage().persistent().has(&key) {
return Err(CredentialRegistryError::CredentialAlreadyExists);
}
let record: (Bytes, Bytes, Bytes, i128, i32) = (
issuer_did.clone(),
subject_did.clone(),
Expand All @@ -66,10 +73,15 @@ impl CredentialRegistryContract {
expires_at,
}
.publish(env);
Ok(())
}

// Revoke a credential. Caller must be issuer (signed address)
pub fn revoke_credential(env: &Env, credential_hash: BytesN<32>, issuer: Address) {
pub fn revoke_credential(
env: &Env,
credential_hash: BytesN<32>,
issuer: Address,
) -> Result<(), CredentialRegistryError> {
issuer.require_auth();
let key = (symbol_short!("cred"), credential_hash.clone());
let opt: Option<(Bytes, Bytes, Bytes, i128, i32)> = env.storage().persistent().get(&key);
Expand All @@ -89,8 +101,9 @@ impl CredentialRegistryContract {
subject_did,
}
.publish(env);
Ok(())
}
None => panic!("credential not found"),
None => Err(CredentialRegistryError::CredentialNotFound),
}
}

Expand Down
Loading
Loading