Skip to main content

tribewarez_pot_o/
lib.rs

1//! # tribewarez-pot-o
2//!
3//! Proof of Tensor Optimizations (PoT-O) on-chain program for Solana.
4//!
5//! This crate implements the PoT-O blockchain validation system, which combines proof-of-work
6//! concepts with tensor network analysis to optimize mining rewards. It manages miner accounts,
7//! validates cryptographic proofs submitted by off-chain validators, and distributes rewards
8//! with optional tensor-aware enhancements.
9//!
10//! ## Core Features
11//!
12//! - **Proof Validation**: Validates mining proofs submitted by the off-chain PoT-O validator
13//! - **Miner Management**: Creates and maintains miner accounts with proof history tracking
14//! - **Reward Distribution**: Distributes mining rewards with support for tensor-weighted bonuses
15//! - **Difficulty Adjustment**: Automatically adjusts mining difficulty based on network conditions
16//! - **Tensor Network Support**: v0.2.0 feature for enhanced reward calculations using tensor metrics
17//!
18//! ## Key Instructions
19//!
20//! - `initialize`: Set up the PoT-O configuration (admin-only)
21//! - `register_miner`: Register a new miner account
22//! - `submit_proof`: Submit a mining proof for validation and reward distribution
23//! - `update_pool_config`: Update configuration parameters (admin-only)
24//! - `create_tensor_pool`: Create a tensor network pool for enhanced rewards (admin-only)
25//!
26//! ## Events
27//!
28//! This program emits events for proof submissions, reward distributions, and configuration changes.
29//! See the [`events`] module for detailed event documentation.
30//!
31//! ## Services
32//!
33//! The [`services`] module provides trait implementations for proof validation and reward distribution,
34//! supporting both legacy (v0.1.x) and tensor-aware (v0.2.0) configurations.
35
36use anchor_lang::prelude::*;
37
38// Module declarations
39pub mod events;
40pub mod services;
41
42// Re-export services for use in instructions
43use events::{ProofSubmitted, RewardDistributed};
44use services::{ProofData, ServiceRegistry};
45
46declare_id!("1PoToVa1idator11111111111111111111111111111");
47
48/// PoT-O: Proof of Tensor Optimizations on-chain program.
49/// Validates mining proofs submitted by the off-chain PoT-O validator,
50/// manages miner accounts, distributes rewards, and adjusts difficulty.
51#[program]
52pub mod tribewarez_pot_o {
53    use super::*;
54
55    /// Initialize the PoT-O config. Called once by the admin.
56    ///
57    /// Sets up both v0.1.x and v0.2.0 configuration. Tensor network features
58    /// are disabled by default but can be enabled via update_pool_config.
59    pub fn initialize(ctx: Context<Initialize>, params: InitParams) -> Result<()> {
60        let config = &mut ctx.accounts.config;
61        config.admin = ctx.accounts.admin.key();
62        config.difficulty = params.difficulty;
63        config.mml_threshold = params.mml_threshold;
64        config.path_distance_max = params.path_distance_max;
65        config.reward_per_proof = params.reward_per_proof;
66        config.total_proofs = 0;
67        config.pool_type = params.pool_type;
68        config.swap_program_id = params.swap_program_id;
69        config.bump = ctx.bumps.config;
70
71        // Initialize tensor network fields (v0.2.0)
72        config.tensor_enabled = 0; // Disabled by default, enable via update_pool_config
73        config.s_max = 1_000_000; // 1e6 scale
74        config.bond_dimension = 2; // Default: 2 bonds per vertex
75        config.max_pool_size = 128; // Max 128 miners per entanglement pool
76        config.entropy_weight_factor = 500_000; // 0.5x entropy weight
77        config.network_entropy = 0;
78        config.total_miners = 0;
79        config.active_pools = 0;
80        config.average_coherence = 0;
81
82        Ok(())
83    }
84
85    /// Register a new miner.
86    ///
87    /// Initializes miner account with device type and computes initial coherence
88    /// based on device type if tensor network is enabled.
89    pub fn register_miner(ctx: Context<RegisterMiner>, device_type: u8) -> Result<()> {
90        let miner = &mut ctx.accounts.miner_account;
91        miner.authority = ctx.accounts.authority.key();
92        miner.device_type = device_type;
93        miner.total_proofs = 0;
94        miner.total_rewards = 0;
95        miner.pending_rewards = 0;
96        miner.reputation_score = 0;
97        miner.last_proof_slot = 0;
98        miner.pool_id = Pubkey::default();
99        miner.bump = ctx.bumps.miner_account;
100
101        // Initialize tensor fields (v0.2.0)
102        miner.vertex_id = 0; // Will be assigned by pool service
103        miner.entropy_score = 0; // Will be calculated on first proof
104        miner.coherence = compute_device_coherence(device_type);
105        miner.last_entropy_update = 0;
106        miner.entanglement_count = 0;
107        miner.pool_generation = 0;
108        miner.unlock_probability = 0; // Will be calculated from entropy
109
110        // Emit event
111        let clock = Clock::get()?;
112        emit!(events::MinerRegistered {
113            authority: ctx.accounts.authority.key(),
114            device_type,
115            timestamp: clock.unix_timestamp,
116        });
117
118        Ok(())
119    }
120
121    /// Submit a PoT-O proof. Validates on-chain using ServiceRegistry and distributes rewards.
122    ///
123    /// This instruction delegates validation and reward calculation to the service layer,
124    /// enabling both legacy (v0.1.x) and tensor-aware (v0.2.0) modes based on config.
125    ///
126    /// Flow:
127    /// 1. Instantiate ServiceRegistry based on config.tensor_enabled
128    /// 2. Use ProofValidator to validate proof (standard or tensor-aware)
129    /// 3. Use RewardDistributor to calculate rewards with bonuses
130    /// 4. Update miner stats and emit events
131    pub fn submit_proof(ctx: Context<SubmitProof>, params: ProofParams) -> Result<()> {
132        let config = &ctx.accounts.config;
133        let clock = Clock::get()?;
134
135        // Instantiate appropriate ServiceRegistry based on config
136        let registry = if config.tensor_enabled != 0 {
137            // Tensor-aware mode (v0.2.0)
138            ServiceRegistry::new_tensor_aware(
139                config.s_max,
140                config.bond_dimension,
141                (config.entropy_weight_factor as f64) / 1_000_000.0,
142                config.max_pool_size,
143            )
144        } else {
145            // Legacy mode (v0.1.x)
146            ServiceRegistry::new_legacy()
147        };
148
149        // Prepare proof data for validation
150        let proof_data = ProofData {
151            challenge_id: params.challenge_id,
152            challenge_slot: params.challenge_slot,
153            tensor_result_hash: params.tensor_result_hash,
154            mml_score: params.mml_score,
155            path_signature: params.path_signature,
156            path_distance: params.path_distance,
157            computation_nonce: params.computation_nonce,
158            computation_hash: params.computation_hash,
159        };
160
161        // 1. Validate proof using service
162        let validator = registry.proof_validator();
163        let validated_proof = validator
164            .validate(
165                &proof_data,
166                clock.slot,
167                config.mml_threshold,
168                config.path_distance_max,
169            )
170            .map_err(|e| match e {
171                services::ValidationError::ChallengeExpired => PotOError::ChallengeExpired,
172                services::ValidationError::MmlThresholdNotMet => PotOError::MmlThresholdNotMet,
173                services::ValidationError::PathDistanceTooLarge => PotOError::PathDistanceTooLarge,
174                services::ValidationError::InvalidComputationHash => {
175                    PotOError::InvalidComputationHash
176                }
177                _ => PotOError::InvalidComputationHash, // Other errors map to generic
178            })?;
179
180        // 2. Calculate reward using service
181        let miner_account = &mut ctx.accounts.miner_account;
182        let distributor = registry.reward_distributor();
183        let reward_allocation = distributor.calculate_reward(
184            config.reward_per_proof,
185            miner_account.reputation_score,
186            miner_account.pool_id,
187            miner_account.device_type,
188        );
189
190        // 3. Record proof with tensor data
191        let proof_record = &mut ctx.accounts.proof_record;
192        proof_record.miner = ctx.accounts.miner.key();
193        proof_record.challenge_id = params.challenge_id;
194        proof_record.mml_score = params.mml_score;
195        proof_record.path_signature = params.path_signature;
196        proof_record.slot = clock.slot;
197        proof_record.timestamp = clock.unix_timestamp;
198        proof_record.reward_distributed = reward_allocation.total_reward;
199        proof_record.bump = ctx.bumps.proof_record;
200
201        // New fields in v0.2.0
202        proof_record.entropy_score = validated_proof.entropy_score;
203        proof_record.is_tensor_aware = if registry.is_tensor_aware() { 1 } else { 0 };
204        proof_record.path_distance = params.path_distance;
205        proof_record.device_type = miner_account.device_type;
206
207        // 4. Update miner stats
208        miner_account.total_proofs += 1;
209        miner_account.pending_rewards += reward_allocation.total_reward;
210        miner_account.last_proof_slot = clock.slot;
211        miner_account.reputation_score += 1;
212
213        // Update tensor fields
214        miner_account.entropy_score = validated_proof.entropy_score;
215        if registry.is_tensor_aware() {
216            miner_account.last_entropy_update = clock.slot;
217        }
218
219        // 5. Update global stats
220        let cfg = &mut ctx.accounts.config;
221        cfg.total_proofs += 1;
222        if registry.is_tensor_aware() {
223            cfg.network_entropy = cfg
224                .network_entropy
225                .saturating_add(validated_proof.entropy_score);
226        }
227
228        // 6. Emit events
229        emit!(ProofSubmitted {
230            miner: ctx.accounts.miner.key(),
231            challenge_id: params.challenge_id,
232            mml_score: params.mml_score,
233            slot: clock.slot,
234            timestamp: clock.unix_timestamp,
235            entropy_score: validated_proof.entropy_score,
236            is_tensor_aware: registry.is_tensor_aware(),
237        });
238
239        emit!(RewardDistributed {
240            miner: ctx.accounts.miner.key(),
241            base_reward: reward_allocation.base_reward,
242            bonus_reward: reward_allocation.bonus_reward,
243            total_reward: reward_allocation.total_reward,
244            multiplier: (reward_allocation.multiplier * 1_000_000.0) as u64, // Convert f64 to u64
245            timestamp: clock.unix_timestamp,
246        });
247
248        Ok(())
249    }
250
251    /// Adjust difficulty (admin or time-gated crank).
252    ///
253    /// Can also adjust entropy weight factor and other tensor parameters.
254    pub fn adjust_difficulty(
255        ctx: Context<AdjustDifficulty>,
256        new_difficulty: u64,
257        new_mml_threshold: u64,
258        new_path_distance_max: u32,
259    ) -> Result<()> {
260        let config = &mut ctx.accounts.config;
261        config.difficulty = new_difficulty;
262        config.mml_threshold = new_mml_threshold;
263        config.path_distance_max = new_path_distance_max;
264        Ok(())
265    }
266
267    /// Claim accumulated rewards.
268    ///
269    /// Transfers accumulated pending rewards to the miner's authority.
270    /// In production, this would include CPI to SPL token program.
271    pub fn claim_rewards(ctx: Context<ClaimRewards>) -> Result<()> {
272        let miner = &mut ctx.accounts.miner_account;
273        let pending = miner.pending_rewards;
274        require!(pending > 0, PotOError::NoRewardsToClaim);
275
276        miner.total_rewards += pending;
277        miner.pending_rewards = 0;
278
279        // In production: CPI transfer of PTtC/NMTC tokens here.
280        // For now, reward accounting is on-chain only.
281
282        let _clock = Clock::get()?;
283        msg!("Rewards claimed: {} tokens", pending);
284
285        Ok(())
286    }
287
288    /// Update pool configuration (admin only).
289    ///
290    /// Can enable/disable tensor network features and configure pool parameters.
291    pub fn update_pool_config(
292        ctx: Context<UpdatePoolConfig>,
293        pool_type: u8,
294        swap_program_id: Pubkey,
295    ) -> Result<()> {
296        let config = &mut ctx.accounts.config;
297        config.pool_type = pool_type;
298        config.swap_program_id = swap_program_id;
299        Ok(())
300    }
301
302    /// Enable or update tensor network configuration (admin only).
303    ///
304    /// Called to enable tensor network features and set entropy parameters.
305    /// Parameters:
306    /// - enable: 1 to enable, 0 to disable tensor network
307    /// - s_max: Maximum entropy (1e6 scale)
308    /// - bond_dimension: Quantum bond dimension (typically 2-4)
309    /// - max_pool_size: Maximum miners per entanglement pool
310    /// - entropy_weight: Entropy weight factor (in 1e6 scale)
311    pub fn configure_tensor_network(
312        ctx: Context<UpdatePoolConfig>,
313        enable: u8,
314        s_max: u64,
315        bond_dimension: u32,
316        max_pool_size: u32,
317        entropy_weight: u64,
318    ) -> Result<()> {
319        let config = &mut ctx.accounts.config;
320        config.tensor_enabled = enable;
321        if enable != 0 {
322            config.s_max = s_max.max(1_000_000); // Minimum 1e6
323            config.bond_dimension = bond_dimension.clamp(2, 8); // Between 2 and 8
324            config.max_pool_size = max_pool_size.clamp(2, 512); // Between 2 and 512
325            config.entropy_weight_factor = entropy_weight;
326        }
327        Ok(())
328    }
329
330    /// Request a token swap via CPI to tribewarez-swap (extension point).
331    pub fn request_swap(
332        _ctx: Context<RequestSwap>,
333        _from_token_mint: Pubkey,
334        _to_token_mint: Pubkey,
335        _amount: u64,
336    ) -> Result<()> {
337        // Extension point: CPI into tribewarez-swap program.
338        // Stub: log and succeed for now.
339        msg!("Swap request received (CPI to tribewarez-swap pending)");
340        Ok(())
341    }
342}
343
344// ---------------------------------------------------------------------------
345// Helper
346// ---------------------------------------------------------------------------
347
348/// Compute initial coherence factor for a device type.
349///
350/// Coherence preservation capabilities (1e6 scale):
351/// - Device 0 (CPU): 0.6 - moderate decoherence
352/// - Device 1 (GPU): 0.8 - good coherence
353/// - Device 2 (ASIC): 1.0 - excellent coherence (baseline)
354/// - Device 3 (Mobile): 0.4 - significant decoherence
355fn compute_device_coherence(device_type: u8) -> u64 {
356    match device_type {
357        0 => 600_000,   // CPU: 0.6x
358        1 => 800_000,   // GPU: 0.8x
359        2 => 1_000_000, // ASIC: 1.0x (baseline)
360        3 => 400_000,   // Mobile: 0.4x
361        _ => 500_000,   // Unknown: 0.5x (conservative)
362    }
363}
364
365// ---------------------------------------------------------------------------
366// Accounts
367// ---------------------------------------------------------------------------
368
369/// Parameters for initializing the PoT-O configuration.
370/// These values are set once during program initialization and can be updated via `update_pool_config`.
371#[derive(AnchorSerialize, AnchorDeserialize)]
372pub struct InitParams {
373    /// Base difficulty threshold for mining proofs
374    pub difficulty: u64,
375    /// Minimum MML (Merkle Merkle Linkage) score required for valid proofs
376    pub mml_threshold: u64,
377    /// Maximum neural path distance allowed in tensor network validation
378    pub path_distance_max: u32,
379    /// Base reward amount distributed per validated proof
380    pub reward_per_proof: u64,
381    /// Pool type (0 = legacy, 1 = tensor-aware v0.2.0)
382    pub pool_type: u8,
383    /// Swap program ID for fee collection functionality
384    pub swap_program_id: Pubkey,
385}
386
387#[derive(AnchorSerialize, AnchorDeserialize)]
388/// Parameters for submitting and validating mining proofs.
389/// Contains cryptographic commitments and validation data for the proof.
390pub struct ProofParams {
391    /// Unique challenge identifier for this mining round
392    pub challenge_id: [u8; 32],
393    /// Solana slot number when the challenge was issued
394    pub challenge_slot: u64,
395    /// Hash of the tensor computation result
396    pub tensor_result_hash: [u8; 32],
397    /// Merkle Merkle Linkage score derived from the proof
398    pub mml_score: u64,
399    /// Signature proving path through the neural network
400    pub path_signature: [u8; 32],
401    /// Distance traveled in the neural path (must be <= path_distance_max)
402    pub path_distance: u32,
403    /// Nonce used in the computation
404    pub computation_nonce: u64,
405    /// Hash of the complete computation (verified against submitted hash)
406    pub computation_hash: [u8; 32],
407}
408
409/// Global PoT-O configuration account.
410/// Stores network-wide settings for proof validation, reward distribution, and tensor network parameters.
411/// This is a singleton account (one per program) created by the admin during initialization.
412#[account]
413pub struct PotOConfig {
414    /// Admin/authority account that can update configuration
415    pub admin: Pubkey,
416    /// Base difficulty threshold for mining proofs
417    pub difficulty: u64,
418    /// Minimum MML score required for valid proofs
419    pub mml_threshold: u64,
420    /// Maximum neural path distance allowed
421    pub path_distance_max: u32,
422    /// Base reward amount per validated proof
423    pub reward_per_proof: u64,
424    /// Total number of proofs submitted since inception
425    pub total_proofs: u64,
426    /// Pool type: 0 = legacy v0.1.x, 1 = tensor-aware v0.2.0
427    pub pool_type: u8,
428    /// Program ID of the swap program for fee collection
429    pub swap_program_id: Pubkey,
430    /// PDA bump seed for this account
431    pub bump: u8,
432
433    // --- v0.2.0 Tensor Network Extensions ---
434    // New fields added at end for ABI compatibility
435    /// Whether tensor network enhancements are enabled
436    pub tensor_enabled: u8, // 0 = disabled, 1 = enabled
437    /// Maximum entropy (1e6 scale)
438    pub s_max: u64, // Maximum entropy (1e6 scale)
439    /// Quantum bond dimension for tensor network calculations
440    pub bond_dimension: u32, // Quantum bond dimension
441    /// Maximum miners allowed per entanglement pool
442    pub max_pool_size: u32, // Maximum miners per pool
443    /// Weight factor for entropy in reward calculations (1e6 scale)
444    pub entropy_weight_factor: u64, // Entropy weight in 1e6 scale
445    /// Current network-wide entropy measurement
446    pub network_entropy: u64, // Current network entropy
447    /// Total number of active miners in the network
448    pub total_miners: u32, // Number of active miners
449    /// Number of active entanglement pools
450    pub active_pools: u32, // Number of entanglement pools
451    /// Average coherence score across all devices (1e6 scale)
452    pub average_coherence: u64, // Average device coherence (1e6 scale)
453
454    // Reserved for future expansion (256 bytes total)
455    /// Reserved space for future updates without breaking ABI compatibility
456    pub reserved: [u8; 200],
457}
458
459/// Per-miner account storing mining history and statistics.
460/// Created when a miner first registers. Updated each time a proof is submitted.
461#[account]
462pub struct MinerAccount {
463    /// Public key of the miner who owns this account
464    pub authority: Pubkey,
465    /// Type of hardware used by this miner
466    pub device_type: u8,
467    /// Total number of valid proofs submitted by this miner
468    pub total_proofs: u64,
469    /// Total rewards distributed to this miner
470    pub total_rewards: u64,
471    /// Pending rewards awaiting claim
472    pub pending_rewards: u64,
473    /// Reputation score based on submission quality (higher is better)
474    pub reputation_score: u64,
475    /// Solana slot of the last valid proof submission
476    pub last_proof_slot: u64,
477    /// ID of the tensor pool this miner is associated with (if any)
478    pub pool_id: Pubkey,
479    /// PDA bump seed for this account
480    pub bump: u8,
481
482    // --- v0.2.0 Tensor Network Extensions ---
483    // New fields added at end for ABI compatibility
484    /// Vertex position in the tensor network graph
485    pub vertex_id: u32, // Position in tensor network graph
486    /// Miner's contribution to network entropy (1e6 scale)
487    pub entropy_score: u64, // Miner's entropy contribution (1e6 scale)
488    /// Device's ability to preserve quantum coherence (1e6 scale, 0-1000000)
489    pub coherence: u64, // Device coherence preservation (1e6 scale)
490    /// Last slot when this miner's entropy metrics were updated
491    pub last_entropy_update: u64, // Last slot when entropy was updated
492    /// Number of other miners this miner is entangled with
493    pub entanglement_count: u32, // Number of entangled connections
494    /// Current pool generation/epoch
495    pub pool_generation: u64, // Generation/epoch of current pool
496    /// Probability of unlock based on entropy (1e6 scale, 0-1000000)
497    pub unlock_probability: u64, // P(unlock) calculated from entropy (1e6 scale)
498
499    // Reserved for future expansion (256 bytes total)
500    /// Reserved space for future updates without breaking ABI compatibility
501    pub reserved: [u8; 192],
502}
503
504/// Proof record account storing details of a submitted mining proof.
505/// Created each time a miner submits a valid proof.
506#[account]
507pub struct ProofRecord {
508    /// Miner who submitted this proof
509    pub miner: Pubkey,
510    /// Unique challenge ID for this proof
511    pub challenge_id: [u8; 32],
512    /// Merkle Merkle Linkage score for this proof
513    pub mml_score: u64,
514    /// Cryptographic signature proving path through neural network
515    pub path_signature: [u8; 32],
516    /// Solana slot when the proof was submitted
517    pub slot: u64,
518    /// Timestamp when the proof was submitted
519    pub timestamp: i64,
520    /// Reward amount that was distributed for this proof
521    pub reward_distributed: u64,
522    /// PDA bump seed for this account
523    pub bump: u8,
524
525    // --- v0.2.0 Tensor Network Extensions ---
526    /// Entropy score calculated from this proof (1e6 scale)
527    pub entropy_score: u64, // Calculated entropy for this proof
528    /// Whether this proof was validated using tensor-aware logic
529    pub is_tensor_aware: u8, // 0 = standard, 1 = tensor-aware validation
530    /// Distance traveled in the neural path
531    pub path_distance: u32, // Neural path distance
532    /// Type of device that submitted this proof
533    pub device_type: u8, // Device type that submitted proof
534}
535
536// ---------------------------------------------------------------------------
537// Contexts
538// ---------------------------------------------------------------------------
539
540#[derive(Accounts)]
541pub struct Initialize<'info> {
542    #[account(
543        init,
544        payer = admin,
545        space = 8 + 32 + 8 + 8 + 4 + 8 + 8 + 1 + 32 + 1 + 1 + 8 + 4 + 4 + 8 + 8 + 4 + 4 + 8 + 200,
546        seeds = [b"pot_o_config"],
547        bump
548    )]
549    pub config: Account<'info, PotOConfig>,
550    #[account(mut)]
551    pub admin: Signer<'info>,
552    pub system_program: Program<'info, System>,
553}
554
555#[derive(Accounts)]
556pub struct RegisterMiner<'info> {
557    #[account(
558        init,
559        payer = authority,
560        space = 8 + 32 + 1 + 8 + 8 + 8 + 8 + 8 + 32 + 1 + 4 + 8 + 8 + 8 + 4 + 8 + 8 + 192,
561        seeds = [b"miner", authority.key().as_ref()],
562        bump
563    )]
564    pub miner_account: Account<'info, MinerAccount>,
565    #[account(mut)]
566    pub authority: Signer<'info>,
567    pub system_program: Program<'info, System>,
568}
569
570#[derive(Accounts)]
571#[instruction(params: ProofParams)]
572pub struct SubmitProof<'info> {
573    #[account(
574        mut,
575        seeds = [b"pot_o_config"],
576        bump = config.bump,
577    )]
578    pub config: Account<'info, PotOConfig>,
579    /// CHECK: miner pubkey used for PDA derivation; identity is in instruction data
580    pub miner: AccountInfo<'info>,
581    #[account(
582        mut,
583        seeds = [b"miner", miner.key().as_ref()],
584        bump = miner_account.bump,
585    )]
586    pub miner_account: Account<'info, MinerAccount>,
587    #[account(
588        init,
589        payer = relayer,
590        space = 8 + 32 + 32 + 8 + 32 + 8 + 8 + 8 + 1 + 8 + 1 + 4 + 1,
591        seeds = [b"proof", params.challenge_id.as_ref()],
592        bump
593    )]
594    pub proof_record: Account<'info, ProofRecord>,
595    #[account(mut)]
596    pub relayer: Signer<'info>,
597    pub system_program: Program<'info, System>,
598}
599
600#[derive(Accounts)]
601pub struct AdjustDifficulty<'info> {
602    #[account(
603        mut,
604        seeds = [b"pot_o_config"],
605        bump = config.bump,
606        has_one = admin,
607    )]
608    pub config: Account<'info, PotOConfig>,
609    pub admin: Signer<'info>,
610}
611
612#[derive(Accounts)]
613pub struct ClaimRewards<'info> {
614    #[account(
615        mut,
616        seeds = [b"miner", authority.key().as_ref()],
617        bump = miner_account.bump,
618    )]
619    pub miner_account: Account<'info, MinerAccount>,
620    pub authority: Signer<'info>,
621}
622
623#[derive(Accounts)]
624pub struct UpdatePoolConfig<'info> {
625    #[account(
626        mut,
627        seeds = [b"pot_o_config"],
628        bump = config.bump,
629        has_one = admin,
630    )]
631    pub config: Account<'info, PotOConfig>,
632    pub admin: Signer<'info>,
633}
634
635#[derive(Accounts)]
636pub struct RequestSwap<'info> {
637    #[account(
638        seeds = [b"pot_o_config"],
639        bump = config.bump,
640    )]
641    pub config: Account<'info, PotOConfig>,
642    #[account(mut)]
643    pub authority: Signer<'info>,
644}
645
646// ---------------------------------------------------------------------------
647// Errors
648// ---------------------------------------------------------------------------
649
650#[error_code]
651pub enum PotOError {
652    #[msg("Challenge has expired (> 256 slots old)")]
653    ChallengeExpired,
654    #[msg("MML score does not meet the required threshold")]
655    MmlThresholdNotMet,
656    #[msg("Neural path distance exceeds maximum allowed")]
657    PathDistanceTooLarge,
658    #[msg("Computation hash does not match expected value")]
659    InvalidComputationHash,
660    #[msg("No rewards available to claim")]
661    NoRewardsToClaim,
662}