Skip to content
Open
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
4 changes: 4 additions & 0 deletions architectures/decentralized/solana-client/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,13 @@ pub async fn build_app(
// Construct RunDownClient using the wallet keypair for signing.
// This enables GCS checkpoint upload/download via run-down signed URLs.
let run_down_keypair = wallet_keypair.clone();
let authorization_grantee = authorizer
.unwrap_or_else(|| wallet_keypair.pubkey())
.to_string();
let run_down_client = Arc::new(RunDownClient::new(
p.run_id.clone(),
wallet_keypair.pubkey().to_string(),
authorization_grantee,
move |msg| run_down_keypair.sign_message(msg).as_ref().to_vec(),
));
checkpoint_config.run_down_client = Some(run_down_client);
Expand Down
5 changes: 5 additions & 0 deletions shared/data-provider/src/run_down.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct RunDownClient {
http: reqwest::Client,
run_id: String,
wallet_address: String,
authorization_grantee: String,
sign_fn: Arc<SignFn>,
}

Expand All @@ -34,12 +35,14 @@ impl RunDownClient {
pub fn new(
run_id: String,
wallet_address: String,
authorization_grantee: String,
sign_fn: impl Fn(&[u8]) -> Vec<u8> + Send + Sync + 'static,
) -> Self {
Self {
http: reqwest::Client::new(),
run_id,
wallet_address,
authorization_grantee,
sign_fn: Arc::new(sign_fn),
}
}
Expand Down Expand Up @@ -73,6 +76,7 @@ impl RunDownClient {
let url = format!("{}/upload/{}", base_url(), self.run_id);
let body = serde_json::json!({
"walletAddress": self.wallet_address,
"authorizationGrantee": self.authorization_grantee,
"filename": filename,
"expiresInSeconds": expires_in_seconds,
"nonce": nonce.to_string(),
Expand Down Expand Up @@ -113,6 +117,7 @@ impl RunDownClient {
let url = format!("{}/download/{}", base_url(), self.run_id);
let body = serde_json::json!({
"walletAddress": self.wallet_address,
"authorizationGrantee": self.authorization_grantee,
"expiresInSeconds": expires_in_seconds,
"nonce": nonce.to_string(),
});
Expand Down
17 changes: 15 additions & 2 deletions tools/rust-tools/run-manager/src/commands/run/download_results.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::path::PathBuf;

use crate::commands::Command;
use anchor_client::solana_sdk::pubkey::Pubkey;
use anyhow::{Context, Result, bail};
use async_trait::async_trait;
use clap::Args;
Expand All @@ -25,6 +26,9 @@ pub struct CommandDownloadResults {

#[clap(long)]
pub overwrite: bool,

#[clap(long, env)]
pub authorizer: Pubkey,
}

#[async_trait]
Expand All @@ -35,6 +39,7 @@ impl Command for CommandDownloadResults {
output_dir,
expires_in_seconds,
overwrite,
authorizer,
} = self;

// Check if output directory exists and is not empty
Expand Down Expand Up @@ -71,14 +76,22 @@ impl Command for CommandDownloadResults {
let nonce: u64 = rand::random();

// Generate signature for the run-down service
let signature_b58 =
run_down_service::generate_signature(&backend, &run_id, expires_in_seconds, nonce);
let wallet_address = backend.get_payer().to_string();
let signature_b58 = run_down_service::generate_signature(
&backend,
&run_id,
&wallet_address,
expires_in_seconds,
nonce,
);

// Make POST request to the API
let client = reqwest::Client::new();
let urls_response = run_down_service::get_download_urls(
&client,
&run_id,
&wallet_address,
&authorizer.to_string(),
&signature_b58,
expires_in_seconds,
nonce,
Expand Down
25 changes: 19 additions & 6 deletions tools/rust-tools/run-manager/src/commands/run/run_down_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ use anyhow::{Context, Result, bail};
use psyche_solana_rpc::SolanaBackend;
use serde::{Deserialize, Serialize};

const RUN_DOWN_SERVICE_BASE_URL: &str = "https://run-down.nousresearch.com/v1";
fn run_down_base_url() -> String {
std::env::var("RUN_DOWN_URL")
.unwrap_or_else(|_| "https://run-down.nousresearch.com/v1".to_string())
}

/// Generate a signed message for the Nous run-down service API
///
/// Creates a message in the format: `nous-run-down-service:{run_id}:{expires_in_seconds}:{nonce}`
/// Creates a message in the format: `nous-run-down-service:{run_id}:{wallet_address}:{expires_in_seconds}:{nonce}`
/// and signs it using the provided backend's wallet.
///
/// Returns the base58-encoded signature.
pub fn generate_signature(
backend: &SolanaBackend,
run_id: &str,
wallet_address: &str,
expires_in_seconds: u64,
nonce: u64,
) -> String {
let message = format!(
"nous-run-down-service:{}:{}:{}",
run_id, expires_in_seconds, nonce
"nous-run-down-service:{}:{}:{}:{}",
run_id, wallet_address, expires_in_seconds, nonce
);
let message_bytes = message.as_bytes();
let signature = backend.sign_message(message_bytes);
Expand Down Expand Up @@ -60,17 +64,22 @@ pub struct UploadUrlResponse {
}

/// Get a signed upload URL for a file
#[allow(clippy::too_many_arguments)]
pub async fn get_upload_url(
client: &reqwest::Client,
run_id: &str,
wallet_address: &str,
authorization_grantee: &str,
signature: &str,
filename: &str,
expires_in_seconds: u64,
nonce: u64,
) -> Result<UploadUrlResponse> {
let url = format!("{}/upload/{}", RUN_DOWN_SERVICE_BASE_URL, run_id);
let url = format!("{}/upload/{}", run_down_base_url(), run_id);

let body = serde_json::json!({
"walletAddress": wallet_address,
"authorizationGrantee": authorization_grantee,
"filename": filename,
"expiresInSeconds": expires_in_seconds,
"nonce": nonce.to_string(),
Expand Down Expand Up @@ -98,13 +107,17 @@ pub struct DownloadUrlsResponse {
pub async fn get_download_urls(
client: &reqwest::Client,
run_id: &str,
wallet_address: &str,
authorization_grantee: &str,
signature: &str,
expires_in_seconds: u64,
nonce: u64,
) -> Result<DownloadUrlsResponse> {
let url = format!("{}/download/{}", RUN_DOWN_SERVICE_BASE_URL, run_id);
let url = format!("{}/download/{}", run_down_base_url(), run_id);

let body = serde_json::json!({
"walletAddress": wallet_address,
"authorizationGrantee": authorization_grantee,
"expiresInSeconds": expires_in_seconds,
"nonce": nonce.to_string(),
});
Expand Down
17 changes: 15 additions & 2 deletions tools/rust-tools/run-manager/src/commands/run/upload_data.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::path::PathBuf;

use anchor_client::solana_sdk::pubkey::Pubkey;
use anyhow::{Context, Result, bail};
use async_trait::async_trait;
use clap::Args;
Expand All @@ -25,6 +26,9 @@ pub struct CommandUploadData {
/// How long the signed URLs should be valid (in seconds)
#[clap(long, env, default_value = "3600")]
pub expires_in_seconds: u64,

#[clap(long, env)]
pub authorizer: Pubkey,
}

#[async_trait]
Expand All @@ -34,6 +38,7 @@ impl Command for CommandUploadData {
run_id,
path,
expires_in_seconds,
authorizer,
} = self;

// Determine base directory for computing relative paths
Expand Down Expand Up @@ -86,13 +91,21 @@ impl Command for CommandUploadData {
let nonce: u64 = rand::random();

// Generate signature for the run-down service
let signature_b58 =
run_down_service::generate_signature(&backend, &run_id, expires_in_seconds, nonce);
let wallet_address = backend.get_payer().to_string();
let signature_b58 = run_down_service::generate_signature(
&backend,
&run_id,
&wallet_address,
expires_in_seconds,
nonce,
);

// Make POST request to get upload URL
let upload_response = run_down_service::get_upload_url(
&client,
&run_id,
&wallet_address,
&authorizer.to_string(),
&signature_b58,
relative_path,
expires_in_seconds,
Expand Down
Loading