What is a Guest?

A Guest in Holochain is a WebAssembly (WASM) application that runs in a secure sandbox environment provided by the Host. Guests contain the core application logic and interact with the host through a controlled API surface to access system resources, network operations, and persistent storage.

Core Architecture

Guest Execution Model

┌─────────────────────────────────────────┐
│           Guest Application             │
├─────────────────────────────────────────┤
│  • Application Logic (WASM)            │
│  • Business Rules                      │
│  • Validation Functions                │
│  • User Interface Logic                │
└─────────────┬───────────────────────────┘
              │ Host API Calls
┌─────────────▼───────────────────────────┐
│             Host Runtime                │
├─────────────────────────────────────────┤
│  • System Resources                    │
│  • Network Communication               │
│  • Cryptographic Services             │
│  • Data Persistence                   │
└─────────────────────────────────────────┘

WebAssembly Benefits

  • Security: Memory-safe execution with strong isolation
  • Performance: Near-native execution speed
  • Portability: Platform-independent bytecode
  • Language Agnostic: Support for multiple programming languages
  • Sandboxing: No direct system access without explicit permission

Guest Components

Application Logic

// Example guest application structure
#[hdk_extern]
pub fn create_entry(entry_input: CreateEntryInput) -> ExternResult<HeaderHash> {
    // Business logic implementation
    validate_entry_data(&entry_input)?;
    
    // Host API call for persistence
    let header_hash = create_entry(&entry_input.entry)?;
    
    Ok(header_hash)
}

Validation Functions

Guests implement validation rules that ensure data integrity:

#[hdk_extern]
pub fn validate(op: Op) -> ExternResult<ValidateCallbackResult> {
    match op {
        Op::StoreEntry(store_entry) => {
            validate_entry_rules(&store_entry.entry)
        }
        Op::StoreRecord(store_record) => {
            validate_record_rules(&store_record.record)
        }
        _ => Ok(ValidateCallbackResult::Valid),
    }
}

User Interface Integration

// Guest application exposed functions
const guestAPI = {
    // Core operations
    createEntry: (data) => call_guest_function('create_entry', data),
    getEntry: (hash) => call_guest_function('get_entry', hash),
    updateEntry: (hash, data) => call_guest_function('update_entry', { hash, data }),
    
    // Application-specific logic
    validateUser: (credentials) => call_guest_function('validate_user', credentials),
    processTransaction: (txn) => call_guest_function('process_transaction', txn),
};

Development Framework

Holochain Development Kit (HDK)

The HDK provides high-level bindings for guest development:

use hdk::prelude::*;
 
// Entry definition
#[hdk_entry_helper]
#[derive(Clone, PartialEq)]
pub struct BlogPost {
    pub title: String,
    pub content: String,
    pub author: AgentPubKey,
    pub timestamp: Timestamp,
}
 
// Zome functions
#[hdk_extern]
pub fn create_blog_post(post: BlogPost) -> ExternResult<Record> {
    // Validation logic
    if post.title.is_empty() {
        return Err(wasm_error!("Title cannot be empty"));
    }
    
    // Create entry through host
    let action_hash = create_entry(&EntryTypes::BlogPost(post.clone()))?;
    
    // Retrieve created record
    let record = get(action_hash, GetOptions::default())?
        .ok_or(wasm_error!("Could not get the created record"))?;
    
    Ok(record)
}

Language Support

Guests can be written in multiple languages:

Rust (Primary)

#[hdk_extern]
pub fn my_function(input: String) -> ExternResult<String> {
    Ok(format!("Processed: {}", input))
}

JavaScript/TypeScript

export function myFunction(input: string): string {
    return `Processed: ${input}`;
}

AssemblyScript

export function myFunction(input: string): string {
    return "Processed: " + input;
}

Guest Lifecycle

Initialization

#[hdk_extern]
pub fn init(_: ()) -> ExternResult<InitCallbackResult> {
    // Initialize guest state
    setup_application_data()?;
    configure_validation_rules()?;
    
    Ok(InitCallbackResult::Pass)
}

Operation Handling

// Guest handling different operation types
match operation_type {
    OperationType::Create => handle_create_operation(op_data),
    OperationType::Update => handle_update_operation(op_data),
    OperationType::Delete => handle_delete_operation(op_data),
    OperationType::Query => handle_query_operation(op_data),
}

Cleanup

#[hdk_extern]
pub fn cleanup(_: ()) -> ExternResult<CleanupCallbackResult> {
    // Resource cleanup
    clear_temporary_data()?;
    flush_pending_operations()?;
    
    Ok(CleanupCallbackResult::Success)
}

Security Model

Sandbox Restrictions

Guests operate under strict security constraints:

  • No Direct System Access: All system operations through host API
  • Memory Isolation: Cannot access memory outside allocated space
  • Resource Limits: CPU, memory, and time execution bounds
  • API Validation: All host API calls validated and sanitized

Capability Requirements

// Guest requesting capabilities
#[hdk_extern]
pub fn request_network_access() -> ExternResult<()> {
    // Host validates capability request
    let network_cap = request_capability(CapabilityType::Network)?;
    
    // Use capability for network operations
    send_message(network_cap, peer_id, message)?;
    
    Ok(())
}

Input Validation

#[hdk_extern] 
pub fn process_input(data: InputData) -> ExternResult<ProcessedData> {
    // Validate all inputs
    validate_input_format(&data)?;
    validate_input_constraints(&data)?;
    validate_business_rules(&data)?;
    
    // Process validated data
    let result = apply_business_logic(data)?;
    
    Ok(result)
}

Host API Integration

System Calls

Guests access system functionality through host API:

// Cryptographic operations
let signature = sign(private_key, message_data)?;
let is_valid = verify_signature(public_key, signature, message_data)?;
 
// Network operations
let peers = get_peer_list()?;
let response = send_remote_call(target_agent, function_name, payload)?;
 
// Storage operations
let entry_hash = create_entry(entry_data)?;
let entry = get_entry(entry_hash)?;

Error Handling

match host_operation() {
    Ok(result) => process_success(result),
    Err(HostError::NetworkTimeout) => handle_network_error(),
    Err(HostError::ValidationFailed(reason)) => handle_validation_error(reason),
    Err(HostError::InsufficientPermissions) => handle_permission_error(),
    Err(error) => handle_generic_error(error),
}

Performance Considerations

Memory Management

// Efficient memory usage in guests
use hdk::prelude::*;
 
#[hdk_extern]
pub fn process_large_dataset(data: Vec<DataItem>) -> ExternResult<ProcessedResult> {
    // Process in chunks to manage memory
    let chunk_size = 100;
    let mut results = Vec::new();
    
    for chunk in data.chunks(chunk_size) {
        let chunk_result = process_chunk(chunk)?;
        results.push(chunk_result);
        
        // Allow garbage collection between chunks
        yield_to_host()?;
    }
    
    Ok(combine_results(results))
}

Computation Efficiency

#[hdk_extern]
pub fn efficient_computation(input: ComputeInput) -> ExternResult<ComputeResult> {
    // Check computation budget
    check_execution_budget()?;
    
    // Use efficient algorithms
    let result = match input.complexity {
        Low => fast_algorithm(input),
        Medium => balanced_algorithm(input), 
        High => optimized_algorithm(input),
    }?;
    
    Ok(result)
}

Testing and Debugging

Unit Testing

#[cfg(test)]
mod tests {
    use super::*;
    use hdk::test_utils::*;
 
    #[tokio::test]
    async fn test_guest_function() {
        let mut mock_hdk = MockHdkT::new();
        
        // Mock host responses
        mock_hdk.expect_create_entry()
            .returning(|_| Ok(fake_action_hash()));
            
        // Test guest function
        let result = create_blog_post(test_blog_post()).unwrap();
        assert!(!result.action().as_hash().is_empty());
    }
}

Development Tools

  • Holochain Playground: Interactive testing environment
  • HDK Test Utils: Mock host interactions
  • WASM Debugger: Step-through debugging support
  • Performance Profiler: Execution analysis tools

Advanced Patterns

State Management

// Guest state management pattern
lazy_static! {
    static ref GUEST_STATE: Mutex<GuestState> = Mutex::new(GuestState::new());
}
 
#[hdk_extern]
pub fn update_state(update: StateUpdate) -> ExternResult<()> {
    let mut state = GUEST_STATE.lock()?;
    state.apply_update(update)?;
    persist_state(&state)?;
    
    Ok(())
}

Event Handling

#[hdk_extern]
pub fn handle_signal(signal: ExternIO) -> ExternResult<()> {
    let event: ApplicationEvent = signal.decode()?;
    
    match event.event_type {
        EventType::UserAction => handle_user_event(event),
        EventType::NetworkEvent => handle_network_event(event),
        EventType::SystemEvent => handle_system_event(event),
    }
}

Inter-Cell Communication

#[hdk_extern]
pub fn cross_cell_operation(target_cell: CellId, operation: Operation) -> ExternResult<Response> {
    // Call function in another cell
    let response = call(
        CallTargetCell::Other(target_cell),
        ZomeName("coordinator".into()),
        FunctionName("process_operation".into()),
        None,
        operation,
    )?;
    
    Ok(response)
}
  • Host - Runtime environment that executes guest applications
  • Cells - Container for guest application instances
  • WebAssembly - Execution format for guest applications
  • HDK - Development kit for building guest applications
  • Conductor - Host implementation that manages guests

External Resources