Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

very basic validator functionality #96

Merged
merged 12 commits into from
Feb 12, 2025
Merged
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
261 changes: 228 additions & 33 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ watch-discovery:

watch-miner:
set -a; source ${ENV_FILE}; set +a; \
cargo watch -w miner/src -x "run --bin miner -- run --private-key-provider $$PROVIDER_PRIVATE_KEY --private-key-node $$NODE_PRIVATE_KEY --port 8091 --external-ip 0.0.0.0 --compute-pool-id 0"
cargo watch -w miner/src -x "run --bin miner -- run --private-key-provider $$PROVIDER_PRIVATE_KEY --private-key-node $$NODE_PRIVATE_KEY --port 8091 --external-ip 0.0.0.0 --compute-pool-id 0 --validator-address $$VALIDATOR_ADDRESS"

watch-validator:
set -a; source ${ENV_FILE}; set +a; \
Expand All @@ -88,7 +88,7 @@ build-miner:

run-miner-bin:
set -a; source .env; set +a; \
./target/release/miner run --private-key-provider $$PROVIDER_PRIVATE_KEY --private-key-node $$NODE_PRIVATE_KEY --port 8091 --external-ip 0.0.0.0 --compute-pool-id 0
./target/release/miner run --private-key-provider $$PROVIDER_PRIVATE_KEY --private-key-node $$NODE_PRIVATE_KEY --port 8091 --external-ip 0.0.0.0 --compute-pool-id 0 --validator-address $$VALIDATOR_ADDRESS

SSH_CONNECTION ?= your-ssh-conn string
EXTERNAL_IP ?= 0.0.0.0
Expand Down Expand Up @@ -140,7 +140,8 @@ watch-miner-remote: setup-remote setup-tunnel sync-remote
--private-key-node \$$NODE_PRIVATE_KEY \
--port $(PORT) \
--external-ip \$$EXTERNAL_IP \
--compute-pool-id 0 2>&1 | tee miner.log\""
--compute-pool-id 0 \
--validator-address \$$VALIDATOR_ADDRESS 2>&1 | tee miner.log\""
# Kill SSH tunnel
.PHONY: kill-tunnel
kill-tunnel:
Expand Down
1 change: 1 addition & 0 deletions miner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ chrono = "0.4"
serial_test = "0.5.1"
directories = "6.0.0"
strip-ansi-escapes = "0.2.1"
nalgebra = "0.33.2"

[dev-dependencies]
tempfile = "=3.14.0"
6 changes: 3 additions & 3 deletions miner/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ run-check:

run:
@echo "🔨 Building locally..."
cargo run -- run --subnet-id 1 --private-key-provider $$PRIVATE_KEY_PROVIDER --private-key-node $$NODE_KEY --port 8090 --external-ip 0.0.0.0 --compute-pool-id 0
cargo run -- run --subnet-id 1 --private-key-provider $$PRIVATE_KEY_PROVIDER --private-key-node $$NODE_KEY --port 8090 --external-ip 0.0.0.0 --compute-pool-id 0 --validator-address $$VALIDATOR_ADDRESS

watch:
@echo "👀 Watching for changes..."
cargo watch -x "run -- run --subnet-id 1 --private-key-provider $$PRIVATE_KEY_PROVIDER --private-key-node $$NODE_KEY --port 8090 --external-ip 0.0.0.0 --compute-pool-id 0"
cargo watch -x "run -- run --subnet-id 1 --private-key-provider $$PRIVATE_KEY_PROVIDER --private-key-node $$NODE_KEY --port 8090 --external-ip 0.0.0.0 --compute-pool-id 0 --validator-address $$VALIDATOR_ADDRESS"

# Setup GPU server with required dependencies
gpu-setup:
Expand Down Expand Up @@ -44,4 +44,4 @@ gpu-run:

# Watch mode - automatically deploy and run on file changes
gpu-watch:
cargo watch -x "make gpu-run"
cargo watch -x "make gpu-run"
23 changes: 23 additions & 0 deletions miner/src/api/routes/challenge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::api::server::AppState;
use actix_web::{
web::{self, post, Data},
HttpResponse, Scope,
};
use shared::models::api::ApiResponse;
use shared::models::challenge::calc_matrix;
use shared::models::challenge::ChallengeRequest;

pub async fn handle_challenge(
challenge: web::Json<ChallengeRequest>,
_app_state: Data<AppState>,
) -> HttpResponse {
let result = calc_matrix(&challenge);

let response = ApiResponse::new(true, result);

HttpResponse::Ok().json(response)
}

pub fn challenge_routes() -> Scope {
web::scope("/challenge").route("/submit", post().to(handle_challenge))
}
1 change: 1 addition & 0 deletions miner/src/api/routes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod challenge;
pub mod invite;
pub mod task;
pub mod types;
9 changes: 8 additions & 1 deletion miner/src/api/server.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::api::routes::challenge::challenge_routes;
use crate::api::routes::invite::invite_routes;
use crate::api::routes::task::task_routes;
use crate::docker::DockerService;
use crate::operations::heartbeat::service::HeartbeatService;
use actix_web::{middleware, web::Data, App, HttpServer};
use alloy::primitives::Address;
use shared::security::auth_signature_middleware::{ValidateSignature, ValidatorState};
use shared::web3::contracts::core::builder::Contracts;
use shared::web3::contracts::structs::compute_pool::PoolInfo;
use shared::web3::wallet::Wallet;
use std::str::FromStr;
use std::sync::Arc;

#[derive(Clone)]
Expand All @@ -28,6 +31,7 @@ pub async fn start_server(
heartbeat_service: Arc<HeartbeatService>,
docker_service: Arc<DockerService>,
pool_info: Arc<PoolInfo>,
validator_address: String,
) -> std::io::Result<()> {
println!("Starting server at http://{}:{}", host, port);

Expand All @@ -39,7 +43,9 @@ pub async fn start_server(
docker_service,
});

let allowed_addresses = vec![pool_info.creator, pool_info.compute_manager_key];
let validator = Address::from_str(validator_address.as_str()).unwrap();

let allowed_addresses = vec![pool_info.creator, pool_info.compute_manager_key, validator];
let validator_state = Arc::new(ValidatorState::new(allowed_addresses));

HttpServer::new(move || {
Expand All @@ -49,6 +55,7 @@ pub async fn start_server(
.wrap(ValidateSignature::new(validator_state.clone()))
.service(invite_routes())
.service(task_routes())
.service(challenge_routes())
})
.bind((host, port))?
.run()
Expand Down
5 changes: 5 additions & 0 deletions miner/src/cli/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ pub enum Commands {
// Amount of stake to use when provider is newly registered
#[arg(long, default_value = "10")]
provider_stake: i32,

#[arg(long, default_value = "0x0000000000000000000000000000000000000000")]
validator_address: Option<String>,
},
/// Run system checks to verify hardware and software compatibility
Check {},
Expand All @@ -104,6 +107,7 @@ pub async fn execute_command(
state_dir_overwrite,
disable_state_storing,
auto_recover,
validator_address,
} => {
if *disable_state_storing && *auto_recover {
Console::error(
Expand Down Expand Up @@ -345,6 +349,7 @@ pub async fn execute_command(
heartbeat_clone.clone(),
docker_service.clone(),
pool_info,
validator_address.clone().unwrap_or_default(),
)
.await
} {
Expand Down
1 change: 1 addition & 0 deletions shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ uuid = { version = "1.12.1", features = ["v4", "serde"] }
redis = "0.28.1"
dashmap = "6.1.0"
anyhow = "1.0.95"
nalgebra = "0.33.2"
88 changes: 88 additions & 0 deletions shared/src/models/challenge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use nalgebra::DMatrix;
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt;

#[derive(Debug, Clone)]
pub struct FixedF64(pub f64);

impl Serialize for FixedF64 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// adjust precision as needed
serializer.serialize_str(&format!("{:.12}", self.0))
}
}

impl<'de> Deserialize<'de> for FixedF64 {
fn deserialize<D>(deserializer: D) -> Result<FixedF64, D::Error>
where
D: Deserializer<'de>,
{
struct FixedF64Visitor;

impl Visitor<'_> for FixedF64Visitor {
type Value = FixedF64;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string representing a fixed precision float")
}

fn visit_str<E>(self, value: &str) -> Result<FixedF64, E>
where
E: de::Error,
{
value
.parse::<f64>()
.map(FixedF64)
.map_err(|_| E::custom(format!("invalid f64: {}", value)))
}
}

deserializer.deserialize_str(FixedF64Visitor)
}
}

impl PartialEq for FixedF64 {
fn eq(&self, other: &Self) -> bool {
format!("{:.10}", self.0) == format!("{:.10}", other.0)
}
}

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct ChallengeRequest {
pub rows_a: usize,
pub cols_a: usize,
pub data_a: Vec<FixedF64>,
pub rows_b: usize,
pub cols_b: usize,
pub data_b: Vec<FixedF64>,
}

#[derive(Deserialize, Serialize, Debug)]
pub struct ChallengeResponse {
pub result: Vec<FixedF64>,
pub rows: usize,
pub cols: usize,
}

pub fn calc_matrix(req: &ChallengeRequest) -> ChallengeResponse {
// convert FixedF64 to f64
let data_a: Vec<f64> = req.data_a.iter().map(|x| x.0).collect();
let data_b: Vec<f64> = req.data_b.iter().map(|x| x.0).collect();
let a = DMatrix::from_vec(req.rows_a, req.cols_a, data_a);
let b = DMatrix::from_vec(req.rows_b, req.cols_b, data_b);
let c = a * b;

let data_c: Vec<FixedF64> = c.iter().map(|x| FixedF64(*x)).collect();

ChallengeResponse {
rows: c.nrows(),
cols: c.ncols(),
result: data_c,
}
}
1 change: 1 addition & 0 deletions shared/src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod api;
pub mod challenge;
pub mod heartbeat;
pub mod invite;
pub mod metric;
Expand Down
2 changes: 2 additions & 0 deletions validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ anyhow = "1.0.95"
clap = { version = "4.5.26", features = ["derive"] }
env_logger = "0.11.6"
log = "0.4.25"
nalgebra = "0.33.2"
rand = "0.9.0"
reqwest = "0.12.12"
serde = "1.0.217"
serde_json = "1.0.135"
Expand Down
Loading