diff --git a/architectures/decentralized/solana-common/src/backend.rs b/architectures/decentralized/solana-common/src/backend.rs index b33d7f4c6..2b0bf8a5e 100644 --- a/architectures/decentralized/solana-common/src/backend.rs +++ b/architectures/decentralized/solana-common/src/backend.rs @@ -258,8 +258,25 @@ impl SolanaBackend { ) -> Result { let coordinator_instance_state = self.get_coordinator_instance(&coordinator_instance).await?; - let authorization = - Self::find_join_authorization(&coordinator_instance_state.join_authority, authorizer); + + // If an authorizer is explicitly provided, use it directly. + // Otherwise, try permissionless first, then fall back to payer's key. + let authorization = if authorizer.is_some() { + Self::find_join_authorization(&coordinator_instance_state.join_authority, authorizer) + } else { + let permissionless_authorization = Self::find_join_authorization( + &coordinator_instance_state.join_authority, + Some(system_program::ID), + ); + if self.get_balance(&permissionless_authorization).await? > 0 { + permissionless_authorization + } else { + Self::find_join_authorization( + &coordinator_instance_state.join_authority, + Some(self.get_payer()), + ) + } + }; let instruction = instructions::coordinator_join_run( &coordinator_instance, &coordinator_account, diff --git a/architectures/decentralized/solana-common/src/retry.rs b/architectures/decentralized/solana-common/src/retry.rs index 03aa23f39..a41487299 100644 --- a/architectures/decentralized/solana-common/src/retry.rs +++ b/architectures/decentralized/solana-common/src/retry.rs @@ -82,6 +82,13 @@ impl From for RetryError { } else if msg.contains("InvalidWitness") { error!("InvalidWitness. Fatal Error."); RetryError::Fatal(ClientError::SolanaClientError(e)) + } else if msg.contains("AccountNotInitialized") + && msg.contains("authorization") + { + error!( + "Your authorization account has not been created. Please ensure you have been authorized to join this run. Fatal Error." + ); + RetryError::Fatal(ClientError::SolanaClientError(e)) } else if msg.contains("Failed to tick") { warn!("Failed to tick. Retryable Error."); RetryError::Retryable(ClientError::SolanaClientError(e)) diff --git a/tools/rust-tools/run-manager/src/commands/can_join.rs b/tools/rust-tools/run-manager/src/commands/can_join.rs index 64a6469dd..77fe02a8a 100644 --- a/tools/rust-tools/run-manager/src/commands/can_join.rs +++ b/tools/rust-tools/run-manager/src/commands/can_join.rs @@ -33,16 +33,41 @@ impl Command for CommandCanJoin { .get_coordinator_instance(&coordinator_instance) .await?; - let authorization = SolanaBackend::find_join_authorization( - &coordinator_instance_state.join_authority, - authorizer, - ); - if backend.get_balance(&authorization).await? == 0 { - bail!( - "Authorization does not exist for authorizer: {authorizer:?} (authorization address: {authorization:?}, join authority: {0:?}). Authorizer must be set to grantee pubkey for permissioned runs", - coordinator_instance_state.join_authority + // If an authorizer is explicitly provided, use it directly. + // Otherwise, try permissionless first, then fall back to the user's address. + let authorization = if let Some(auth) = authorizer { + let authorization = SolanaBackend::find_join_authorization( + &coordinator_instance_state.join_authority, + Some(auth), ); - } + if backend.get_balance(&authorization).await? == 0 { + bail!( + "Authorization does not exist for authorizer: {auth} (authorization address: {authorization}, join authority: {}). Authorizer must be set to grantee pubkey for permissioned runs", + coordinator_instance_state.join_authority + ); + } + authorization + } else { + let permissionless_authorization = SolanaBackend::find_join_authorization( + &coordinator_instance_state.join_authority, + None, + ); + if backend.get_balance(&permissionless_authorization).await? > 0 { + permissionless_authorization + } else { + let fallback_authorization = SolanaBackend::find_join_authorization( + &coordinator_instance_state.join_authority, + Some(address), + ); + if backend.get_balance(&fallback_authorization).await? == 0 { + bail!( + "No valid authorization found for {address}. The run is permissioned and you must have a valid authorization. (join authority: {})", + coordinator_instance_state.join_authority + ); + } + fallback_authorization + } + }; if !backend .get_authorization(&authorization) .await? @@ -54,7 +79,7 @@ impl Command for CommandCanJoin { { bail!("Authorization invalid for run id {run_id} using pubkey {address}"); } - println!("authorization valid for run id {run_id} using pubkey {address}"); + println!("Authorization valid for run id {run_id} using pubkey {address}"); let coordinator_account_state = backend .get_coordinator_account(&coordinator_instance_state.coordinator_account)