Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ upstream_authority_pubkey = "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72
downstream_address = "0.0.0.0"
downstream_port = 34255

# Mint URL for Cashu operations (adjust for hosted environment)
mint_url = "http://127.0.0.1:3338"

# Version support
max_supported_version = 2
min_supported_version = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ upstream_authority_pubkey = "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72
downstream_address = "0.0.0.0"
downstream_port = 34255

# Mint URL for Cashu operations
mint_url = "http://127.0.0.1:3338"

# Version support
max_supported_version = 2
min_supported_version = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ upstream_authority_pubkey = "9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72
downstream_address = "0.0.0.0"
downstream_port = 34255

# Mint URL for Cashu operations
mint_url = "http://127.0.0.1:3338"

# Version support
max_supported_version = 2
min_supported_version = 2
Expand Down
76 changes: 51 additions & 25 deletions roles/translator/src/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::{
net::{IpAddr, SocketAddr},
str::FromStr,
sync::Arc,
collections::HashMap,
};

use tokio::{
Expand Down Expand Up @@ -43,12 +44,11 @@ pub struct TranslatorSv2 {
wallet: Arc<Wallet>,
}

fn create_wallet() -> Arc<Wallet> {
fn create_wallet(mint_url: &str) -> Arc<Wallet> {
use cdk::cdk_database::WalletMemoryDatabase;
use cdk::nuts::CurrencyUnit;

let seed = rand::thread_rng().gen::<[u8; 32]>();
let mint_url = "http://127.0.0.1:3338";

let localstore = WalletMemoryDatabase::default();
Arc::new(Wallet::new(mint_url, CurrencyUnit::Custom(HASH_CURRENCY_UNIT.to_string()), Arc::new(localstore), &seed, None).unwrap())
Expand All @@ -59,9 +59,9 @@ impl TranslatorSv2 {
let mut rng = rand::thread_rng();
let wait_time = rng.gen_range(0..=3000);
Self {
wallet: create_wallet(&config.mint_url),
config,
reconnect_wait_time: wait_time,
wallet: create_wallet(),
}
}

Expand Down Expand Up @@ -308,6 +308,7 @@ impl TranslatorSv2 {

fn spawn_proof_sweeper(&self) {
let wallet = self.wallet.clone();
let mint_url = self.config.mint_url.clone();
task::spawn_blocking(move || {
let mut conn = match Self::connect_to_redis("redis://localhost:6379") {
Some(c) => c,
Expand All @@ -326,9 +327,7 @@ impl TranslatorSv2 {
}
};

for quote in &quotes {
Self::process_quote(&wallet, &mut conn, &rt, quote);
}
Self::process_quotes_batch(&wallet, &mut conn, &rt, &quotes, &mint_url);

thread::sleep(Duration::from_secs(60));
}
Expand All @@ -345,32 +344,59 @@ impl TranslatorSv2 {
}
}

fn lookup_uuid(conn: &mut Connection, redis_key: &str) -> Option<String> {
loop {
match conn.get(redis_key) {
Ok(val) => break Some(val),
Err(e) if e.kind() == redis::ErrorKind::TypeError => break None,
Err(e) => {
tracing::warn!("Retrying Redis lookup for key {}: {}", redis_key, e);
thread::sleep(Duration::from_secs(1));
fn lookup_uuids_batch(mint_url: &str, share_hashes: &[String]) -> std::collections::HashMap<String, String> {
if share_hashes.is_empty() {
return HashMap::new();
}

let shares = share_hashes.join(",");
let url = format!("{}/v1/mint/quote-ids/share?share_hashes={}", mint_url, shares);

match ureq::get(&url).call() {
Ok(response) => {
match response.into_string() {
Ok(body) => {
match serde_json::from_str::<HashMap<String, String>>(&body) {
Ok(mapping) => mapping,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
match serde_json::from_str::<HashMap<String, String>>(&body) {
Ok(mapping) => mapping,
match serde_json::from_str::<serde_json::Value>(&body) {
Ok(json) => {
let mut result = HashMap::new();
if let Some(quote_ids) = json.get("quote_ids").and_then(|v| v.as_object()) {
for (k, v) in quote_ids {
if let Some(uuid) = v.as_str() {
result.insert(k.clone(), uuid.to_string());
}
}
}
result
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the CDK wallet client to support the new route so we may be able to avoid this whole serde block. I'm still testing it locally but I'll push up the changes so you can take a look.

Err(e) => {
tracing::error!("Failed to parse batch UUID response: {}", e);
HashMap::new()
}
}
}
Err(e) => {
tracing::warn!("Failed to read batch UUID response body: {}", e);
HashMap::new()
}
}
}
Err(e) => {
tracing::warn!("Failed to make batch UUID lookup request: {}", e);
HashMap::new()
}
}
}

fn process_quote(wallet: &Arc<Wallet>, conn: &mut Connection, rt: &Handle, quote: &MintQuote) {
let redis_key = format!("mint:quotes:hash:{}", quote.id);
let Some(uuid) = Self::lookup_uuid(conn, &redis_key) else {
fn process_quotes_batch(wallet: &Arc<Wallet>, conn: &mut Connection, rt: &Handle, quotes: &[MintQuote], mint_url: &str) {
if quotes.is_empty() {
return;
};
}

// TODO get latest keyset
match rt.block_on(wallet.get_mining_share_proofs(&uuid, &quote.id)) {
Ok(_proofs) => {
Self::log_success_and_cleanup(wallet, conn, rt, quote, &redis_key);
}
Err(e) => {
tracing::info!("Failed to mint ehash tokens for share {} error: {}", quote.id, e);
let quote_ids: Vec<String> = quotes.iter().map(|q| q.id.clone()).collect();
let uuid_mapping = Self::lookup_uuids_batch(mint_url, &quote_ids);

for quote in quotes {
if let Some(uuid) = uuid_mapping.get(&quote.id) {
// TODO get latest keyset
match rt.block_on(wallet.get_mining_share_proofs(uuid, &quote.id)) {
Ok(_proofs) => {
let redis_key = format!("mint:quotes:hash:{}", quote.id);
Self::log_success_and_cleanup(wallet, conn, rt, quote, &redis_key);
}
Err(e) => {
tracing::info!("Failed to mint ehash tokens for share {} error: {}", quote.id, e);
}
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions roles/translator/src/lib/proxy_config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use key_utils::Secp256k1PublicKey;
use serde::Deserialize;

fn default_mint_url() -> String {
"http://127.0.0.1:3338".to_string()
}

#[derive(Debug, Deserialize, Clone)]
pub struct ProxyConfig {
pub upstream_address: String,
Expand All @@ -13,6 +17,8 @@ pub struct ProxyConfig {
pub min_extranonce2_size: u16,
pub downstream_difficulty_config: DownstreamDifficultyConfig,
pub upstream_difficulty_config: UpstreamDifficultyConfig,
#[serde(default = "default_mint_url")]
pub mint_url: String,
}

pub struct UpstreamConfig {
Expand Down Expand Up @@ -61,6 +67,7 @@ impl ProxyConfig {
max_supported_version: u16,
min_supported_version: u16,
min_extranonce2_size: u16,
mint_url: String,
) -> Self {
Self {
upstream_address: upstream.address,
Expand All @@ -73,6 +80,7 @@ impl ProxyConfig {
min_extranonce2_size,
downstream_difficulty_config: downstream.difficulty_config,
upstream_difficulty_config: upstream.difficulty_config,
mint_url,
}
}
}
Expand Down