Skip to content
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
111 changes: 56 additions & 55 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# NOTE: When editing this version, also edit the versions in template_built_in/templates/account and account_nft
[workspace.package]
version = "0.15.0"
version = "0.15.1"
edition = "2021"
authors = ["The Tari Development Community"]
repository = "https://github.com/tari-project/tari-ootle"
Expand Down
9 changes: 8 additions & 1 deletion applications/tari_walletd/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub struct Cli {
pub json_rpc_address: Option<SocketAddr>,
#[clap(long, env = "TARI_WALLET_WEB_UI_JSON_RPC_PUBLIC_URL")]
pub web_ui_public_json_rpc_url: Option<String>,
#[clap(short = 'w', long, env = "TARI_WALLET_WEB_UI_JSON_RPC_PUBLIC_URL")]
pub web_ui_listen_addr: Option<SocketAddr>,
#[clap(long, env = "SIGNALING_SERVER_ADDRESS")]
pub signaling_server_address: Option<SocketAddr>,
#[clap(long, short = 'i', alias = "indexer-url")]
Expand Down Expand Up @@ -118,7 +120,12 @@ impl ConfigOverrideProvider for Cli {
file.display().to_string(),
));
}

if let Some(ref listen_addr) = self.web_ui_listen_addr {
overrides.push((
"ootle_wallet_daemon.web_ui_address".to_string(),
listen_addr.to_string(),
));
}
overrides
}
}
Expand Down
37 changes: 15 additions & 22 deletions applications/tari_walletd/src/handlers/accounts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2023 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use std::{collections::HashSet, iter};
use std::{collections::HashSet, iter, time::Duration};

use anyhow::{anyhow, Context};
use axum_extra::headers::authorization::Bearer;
Expand Down Expand Up @@ -30,7 +30,7 @@ use tari_ootle_wallet_sdk::{
stealth_transfer::{StealthTransferParams, TransferOutput},
substate::ValidatorScanResult,
},
models::{BranchAndKeyId, KeyBranch, KeyId, NewAccountData, WalletLockDropGuard},
models::{BranchAndKeyId, KeyBranch, KeyId, NewAccountData},
};
use tari_ootle_wallet_sdk_services::events::TransactionSubmittedEvent;
use tari_template_builtin::ACCOUNT_TEMPLATE_ADDRESS;
Expand Down Expand Up @@ -1005,7 +1005,7 @@ pub async fn handle_stealth_transfer(
// Spawn here is to prevent the async block from being aborted if the caller aborts the request early as this can
// cause funds to remain locked indefinitely.
task::spawn(async move {
let transfer = sdk.stealth_transfer_api().transfer(owner_account, params).await?;
let (lock, transfer) = sdk.stealth_transfer_api().transfer(owner_account, params).await?;
Comment thread
coderabbitai[bot] marked this conversation as resolved.

let transaction = transfer.transaction.authorized_sealed_signer();
let main_pk = transfer.main_signer.public_key().to_byte_type();
Expand All @@ -1031,13 +1031,7 @@ pub async fn handle_stealth_transfer(
if req.dry_run {
// Release the lock immediately as dry run does not submit the transaction
// TODO: maybe transfer() should not lock the outputs if it's a dry run
if let Err(err) = sdk.stealth_outputs_api().release_lock(transfer.lock_id) {
error!(
target: LOG_TARGET,
"Failed to release locked outputs for dry run : {}",
err
);
}
lock.release();
let result = transaction_service.submit_dry_run_transaction(transaction).await;
return match result {
Ok(res) => Ok(StealthTransferResponse {
Expand All @@ -1047,15 +1041,15 @@ pub async fn handle_stealth_transfer(
};
}

let tx_id = sdk
.stealth_transfer_api()
.unlock_on_failure(
transfer.lock_id,
transaction_service
.submit_transaction_with_opts(transaction, None, Some(transfer.lock_id))
.await,
)
let tx_id = transaction_service
.submit_transaction_with_opts(transaction, None, Some(lock.id()))
.await
.context("Transaction failed to submit")?;

// Transaction submitted, we're home free, make sure to allow the lock to persist past this call.
// The wallet will monitor the transaction and release the lock when it's finalized.
lock.keep_locked();

notifier.notify(TransactionSubmittedEvent {
transaction_id: tx_id,
new_account: None,
Expand Down Expand Up @@ -1089,8 +1083,7 @@ pub async fn handle_create_stealth_transfer_statement(
}

let mut required_signers = HashSet::new();
let lock_id = sdk.stealth_outputs_api().create_lock()?;
let lock_guard = WalletLockDropGuard::new(lock_id, sdk.store().clone());
let lock = sdk.locks_api().create_lock_with_timeout(Duration::from_secs(5 * 60))?;
let mut statements = Vec::with_capacity(req.requests.len());
for req in req.requests {
let sender_account = get_account(&req.sender_account, &sdk.accounts_api())?;
Expand Down Expand Up @@ -1120,7 +1113,7 @@ pub async fn handle_create_stealth_transfer_statement(
.as_selection()
.map(|sel| {
sdk.stealth_transfer_api().lock_inputs_for_transfer(
lock_id,
lock.id(),
sender_account.component_address(),
req.resource_address,
amount_to_spend,
Expand Down Expand Up @@ -1181,7 +1174,7 @@ pub async fn handle_create_stealth_transfer_statement(
}

// Return without unlocking the outputs
lock_guard.disarm();
let lock_id = lock.keep_locked();

Ok(AccountsCreateStealthTransferStatementResponse {
statements,
Expand Down
107 changes: 83 additions & 24 deletions applications/tari_walletd/src/handlers/confidential.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2023 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use std::fs;
use std::{fs, time::Duration};

use anyhow::anyhow;
use axum_extra::headers::authorization::Bearer;
Expand All @@ -10,8 +10,12 @@ use log::*;
use rand::rngs::OsRng;
use serde_json::json;
use tari_crypto::{commitment::HomomorphicCommitmentFactory, keys::PublicKey as _, ristretto::RistrettoPublicKey};
use tari_engine_types::{crypto::get_commitment_factory, ToByteType};
use tari_ootle_wallet_crypto::{AlwaysMissLookupTable, IoReaderValueLookup, UnblindedOutputWitness};
use tari_engine_types::{
crypto::{get_commitment_factory, ValueLookupTable},
ToByteType,
};
use tari_ootle_common_types::{displayable::Displayable, optional::Optional};
use tari_ootle_wallet_crypto::{GenerateValueLookup, IoReaderValueLookup, UnblindedOutputWitness};
use tari_ootle_wallet_sdk::models::{ConfidentialOutputModel, KeyBranch, OutputStatus};
use tari_template_lib::types::Amount;
use tari_wallet_daemon_client::{
Expand All @@ -23,6 +27,8 @@ use tari_wallet_daemon_client::{
ConfidentialViewVaultBalanceResponse,
ProofsCancelRequest,
ProofsCancelResponse,
ProofsFinalizeRequest,
ProofsFinalizeResponse,
ProofsGenerateRequest,
ProofsGenerateResponse,
},
Expand Down Expand Up @@ -59,7 +65,7 @@ pub async fn handle_create_transfer_proof(
let vault = sdk
.accounts_api()
.get_vault_by_resource(account.component_address(), &req.resource_address)?;
let lock_id = sdk.confidential_outputs_api().create_lock()?;
let lock = sdk.locks_api().create_lock_with_timeout(Duration::from_secs(5 * 60))?;

let amount_to_transfer = req.amount.checked_add_positive(req.reveal_amount).ok_or_else(|| {
invalid_request(format!(
Expand All @@ -70,13 +76,13 @@ pub async fn handle_create_transfer_proof(
// Lock inputs we're going to spend
let (inputs, total_input_value) =
sdk.confidential_outputs_api()
.lock_outputs_by_amount(lock_id, &vault.id, amount_to_transfer)?;
.lock_outputs_by_amount(lock.id(), &vault.id, amount_to_transfer)?;

info!(
target: LOG_TARGET,
"Locked {} inputs for proof {} worth {} µT",
inputs.len(),
lock_id,
lock.id(),
total_input_value
);

Expand Down Expand Up @@ -165,7 +171,7 @@ pub async fn handle_create_transfer_proof(
memo: None,
public_asset_tag: None,
status: OutputStatus::LockedUnconfirmed,
lock_id: Some(lock_id),
lock_id: Some(lock.id()),
})?;

Some(UnblindedOutputWitness {
Expand All @@ -192,6 +198,8 @@ pub async fn handle_create_transfer_proof(
Amount::zero(),
)?;

let lock_id = lock.keep_locked();

Ok(ProofsGenerateResponse {
proof_id: lock_id,
proof,
Expand All @@ -201,15 +209,54 @@ pub async fn handle_create_transfer_proof(
pub async fn handle_finalize_transfer(
context: &HandlerContext,
token: Option<&Bearer>,
req: ProofsCancelRequest,
) -> Result<ProofsCancelResponse, anyhow::Error> {
req: ProofsFinalizeRequest,
) -> Result<ProofsFinalizeResponse, anyhow::Error> {
let sdk = context.wallet_sdk();
context.check_auth(token, &[JrpcPermission::Admin])?;
let transaction = sdk
.transaction_api()
.get(req.transaction_id)
.optional()?
.ok_or_else(|| {
invalid_params(
"transaction_id",
Some("No such transaction in wallet to finalize proof for"),
)
})?;
let lock_id = sdk
.locks_api()
.get_lock_by_transaction_id(req.transaction_id)
.optional()?;
if lock_id != Some(req.lock_id) {
return Err(invalid_params(
"lock_id",
Some("Lock not associated with this transaction"),
));
}

sdk.confidential_outputs_api()
.finalize_locked_revealed_funds(req.proof_id)?;
sdk.confidential_outputs_api().finalize_outputs_for_lock(req.proof_id)?;
Ok(ProofsCancelResponse {})
match transaction.finalized_diff() {
Some(diff) => {
info!(
target: LOG_TARGET,
"Finalizing locked proof {} for transaction {}",
req.lock_id,
req.transaction_id
);
sdk.locks_api().finalize_lock(req.lock_id, diff)?;
},
None => {
return Err(invalid_params(
"transaction_id",
Some(format!(
"Transaction is not finalized (status = {}, reason = {})",
transaction.status,
transaction.failure_reason_as_string().display()
)),
));
},
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Ok(ProofsFinalizeResponse {})
}

pub async fn handle_cancel_transfer(
Expand All @@ -219,8 +266,7 @@ pub async fn handle_cancel_transfer(
) -> Result<ProofsCancelResponse, anyhow::Error> {
let sdk = context.wallet_sdk();
context.check_auth(token, &[JrpcPermission::Admin])?;
sdk.confidential_outputs_api().release_revealed_funds(req.proof_id)?;
sdk.confidential_outputs_api().release_locked_outputs(req.proof_id)?;
sdk.locks_api().release_lock(req.proof_id)?;
Ok(ProofsCancelResponse {})
}

Expand Down Expand Up @@ -296,7 +342,14 @@ pub async fn handle_view_vault_balance(
Some(file) => {
let mut file = fs::File::open(file)
.map_err(|e| anyhow!("Unable to load value lookup file '{}': {e}", file.display()))?;
let mut lookup = IoReaderValueLookup::load(&mut file)?;
let mut is_logged = false;
let mut lookup = IoReaderValueLookup::load(&mut file)?.with_fallback(move |v| {
if !is_logged {
is_logged = true;
warn!("Using value lookup fallback. This will likely result in very slow lookups.");
}
GenerateValueLookup.lookup(v)
});

block_in_place(|| {
sdk.viewable_balance_api().try_brute_force_commitment_balances(
Expand All @@ -307,14 +360,20 @@ pub async fn handle_view_vault_balance(
)
})?
},
None => block_in_place(|| {
sdk.viewable_balance_api().try_brute_force_commitment_balances(
&view_key.key,
commitments.values().filter_map(|o| o.viewable_balance.as_ref()),
value_range,
&mut AlwaysMissLookupTable,
)
})?,
None => {
warn!(
target: LOG_TARGET,
"No value lookup table configured. This will likely result in very slow lookups."
);
block_in_place(|| {
sdk.viewable_balance_api().try_brute_force_commitment_balances(
&view_key.key,
commitments.values().filter_map(|o| o.viewable_balance.as_ref()),
value_range,
&mut GenerateValueLookup,
)
})?
},
};

info!(target: LOG_TARGET, "Brute force balance lookup took {:.2?}", timer.elapsed());
Expand Down
21 changes: 16 additions & 5 deletions applications/tari_walletd/src/handlers/stealth_utxos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use anyhow::anyhow;
use axum_extra::headers::authorization::Bearer;
use indexmap::IndexMap;
use log::{info, warn};
use tari_ootle_wallet_crypto::{AlwaysMissLookupTable, IoReaderValueLookup};
use tari_engine_types::crypto::ValueLookupTable;
use tari_ootle_wallet_crypto::{GenerateValueLookup, IoReaderValueLookup};
use tari_template_lib::models::UtxoAddress;
use tari_wallet_daemon_client::{
permissions::JrpcPermission,
Expand Down Expand Up @@ -112,7 +113,8 @@ pub async fn handle_decrypt_value(
Some(path) => spawn_blocking(move || {
let mut file = fs::File::open(&path)
.map_err(|e| anyhow!("Unable to load value lookup file '{}': {e}", path.display()))?;
let mut lookup = IoReaderValueLookup::load(&mut file)?;
let lookup = IoReaderValueLookup::load(&mut file)?;

info!(
target: LOG_TARGET,
"Using value lookup table from file '{}' ({}-{}) for brute force balance lookup",
Expand All @@ -135,6 +137,15 @@ pub async fn handle_decrypt_value(
);
}

let mut is_logged = false;
let mut lookup = lookup.with_fallback(move |v| {
if !is_logged {
is_logged = true;
warn!("Using value lookup fallback. This will likely result in very slow lookups.");
}
GenerateValueLookup.lookup(v)
});

let balance = sdk.viewable_balance_api().try_brute_force_commitment_balances(
&view_key.key,
elgamal_proofs.iter(),
Expand All @@ -147,15 +158,15 @@ pub async fn handle_decrypt_value(
None => {
warn!(
target: LOG_TARGET,
"No value lookup table file configured. Generating a temporary lookup table that always misses. \
This will make the brute force balance lookup very slow for high-value outputs."
"No value lookup table file configured. Using a generated value lookup fallback. \
Brute-force may still be slow for very high-value outputs."
);
spawn_blocking(move || {
let balances = sdk.viewable_balance_api().try_brute_force_commitment_balances(
&view_key.key,
elgamal_proofs.iter(),
value_range,
&mut AlwaysMissLookupTable,
&mut GenerateValueLookup,
)?;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
anyhow::Ok(balances)
})
Expand Down
Loading
Loading