Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 6 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions applications/tari_wallet_cli/src/command/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ async fn handle_create(args: CreateArgs, client: &mut WalletDaemonClient) -> Res
.create_account(AccountsCreateRequest {
account_name: args.account_name,
is_default: Some(args.is_default),
key_id: args.key_id,
key_index: args.key_id,
})
.await?;

Expand Down Expand Up @@ -168,7 +168,7 @@ async fn handle_create_free_test_coins(
.create_or_get_account(AccountsCreateOrGetRequest {
account: Some(account),
is_default: None,
key_id: args.key_id,
key_index: args.key_id,
})
.await?;
resp.account
Expand All @@ -179,7 +179,7 @@ async fn handle_create_free_test_coins(
.create_account(AccountsCreateRequest {
account_name: None,
is_default: None,
key_id: args.key_id,
key_index: args.key_id,
})
.await?;
resp.account
Expand Down
6 changes: 3 additions & 3 deletions applications/tari_wallet_cli/src/command/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use clap::Subcommand;
use tari_ootle_wallet_sdk::apis::key_manager::KeyBranch;
use tari_ootle_wallet_sdk::{apis::key_manager::KeyBranch, models::KeyId};
use tari_template_lib::prelude::RistrettoPublicKeyBytes;
use tari_wallet_daemon_client::WalletDaemonClient;

Expand Down Expand Up @@ -66,12 +66,12 @@ impl KeysSubcommand {
}
}

fn print_keys(keys: Vec<(u64, RistrettoPublicKeyBytes, bool)>) {
fn print_keys(keys: Vec<(KeyId, RistrettoPublicKeyBytes, bool)>) {
println!("Key pairs:");
println!();

let mut table = Table::new();
table.set_titles(vec!["Index", "Public Key", "Active"]);
table.set_titles(vec!["KeyId", "Public Key", "Active"]);
for (index, key, is_active) in keys {
table.add_row(table_row![index, key, if is_active { "✅" } else { "" }]);
}
Expand Down
8 changes: 4 additions & 4 deletions applications/tari_wallet_cli/src/command/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ pub async fn handle_submit(args: SubmitArgs, client: &mut WalletDaemonClient) ->
let resp = client
.submit_transaction_dry_run(TransactionSubmitDryRunRequest {
transaction,
signing_key_index: None,
signing_key_id: None,
detect_inputs: common.detect_inputs.unwrap_or(true),
detect_inputs_use_unversioned: true,
proof_ids: vec![],
Expand All @@ -282,7 +282,7 @@ pub async fn handle_submit(args: SubmitArgs, client: &mut WalletDaemonClient) ->
} else {
let request = TransactionSubmitRequest {
transaction,
signing_key_index: None,
signing_key_id: None,
detect_inputs: common.detect_inputs.unwrap_or(true),
detect_inputs_use_unversioned: true,
proof_ids: vec![],
Expand Down Expand Up @@ -335,7 +335,7 @@ async fn handle_submit_manifest(
let resp = client
.submit_transaction_dry_run(TransactionSubmitDryRunRequest {
transaction,
signing_key_index: Some(fee_account.key_index),
signing_key_id: fee_account.owner_key_id,
detect_inputs: common.detect_inputs.unwrap_or(true),
detect_inputs_use_unversioned: true,
proof_ids: vec![],
Expand All @@ -345,7 +345,7 @@ async fn handle_submit_manifest(
} else {
let request = TransactionSubmitRequest {
transaction,
signing_key_index: Some(fee_account.key_index),
signing_key_id: fee_account.owner_key_id,
detect_inputs: common.detect_inputs.unwrap_or(true),
detect_inputs_use_unversioned: true,
proof_ids: vec![],
Expand Down
4 changes: 2 additions & 2 deletions applications/tari_wallet_cli/src/command/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::str::FromStr;
use clap::{Args, Subcommand};
use tari_ootle_common_types::{shard::Shard, ShardGroup};
use tari_wallet_daemon_client::{
types::{AccountOrKeyIndex, ClaimValidatorFeesRequest, GetValidatorFeesRequest},
types::{AccountOrKeyId, ClaimValidatorFeesRequest, GetValidatorFeesRequest},
ComponentAddressOrName,
WalletDaemonClient,
};
Expand Down Expand Up @@ -63,7 +63,7 @@ impl ValidatorSubcommand {
pub async fn handle_get_fees(args: GetFeesArgs, client: &mut WalletDaemonClient) -> Result<(), anyhow::Error> {
let resp = client
.get_validator_fees(GetValidatorFeesRequest {
account_or_key: AccountOrKeyIndex::Account(args.account),
account_or_key: AccountOrKeyId::Account(args.account),
shard_group: args.shard_group,
})
.await?;
Expand Down
1 change: 1 addition & 0 deletions applications/tari_walletd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ axum-jrpc = { workspace = true, features = ["anyhow_error"] }
clap = { workspace = true, features = ["derive", "env"] }
config = { workspace = true }
either = { workspace = true }
hex = { workspace = true }
humantime-serde = { workspace = true }
futures = { workspace = true }
include_dir = { workspace = true, optional = true }
Expand Down
66 changes: 45 additions & 21 deletions applications/tari_walletd/src/handlers/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ use tari_ootle_wallet_sdk_services::events::TransactionSubmittedEvent;
use tari_template_builtin::ACCOUNT_TEMPLATE_ADDRESS;
use tari_template_lib::{
constants::{STEALTH_TARI_RESOURCE_ADDRESS, XTR, XTR_FAUCET_COMPONENT_ADDRESS, XTR_FAUCET_VAULT_ADDRESS},
prelude::ResourceType,
types::Amount,
types::{Amount, ResourceType},
};
use tari_transaction::args;
use tari_wallet_daemon_client::{
Expand Down Expand Up @@ -114,8 +113,13 @@ pub async fn handle_create(
.map(Ok)
.unwrap_or_else(|| accounts_api.any_accounts_exist().map(|b| !b))?;

let owner_address = match req.key_index {
Some(id) => sdk.key_manager_api().derive_account_address(id)?,
None => sdk.key_manager_api().next_account_address()?,
};

let acc = accounts_api
.create_account(req.account_name.as_deref(), set_as_default, req.key_id)
.create_account(req.account_name.as_deref(), set_as_default, owner_address)
.map_err(|e| {
if e.is_name_exists_error() {
invalid_request(e)
Expand Down Expand Up @@ -158,8 +162,8 @@ pub async fn handle_create_or_get(
Some(ComponentAddressOrName::Name(ref name)) => accounts_api.get_account_by_name(name).optional()?,
// If we cannot find an account with this key index, we'll create one
None => req
.key_id
.map(|id| get_account_by_key_index(sdk, id).optional())
.key_index
.map(|index| get_account_by_key_index(sdk, index).optional())
.transpose()?
.flatten(),
};
Expand All @@ -181,8 +185,13 @@ pub async fn handle_create_or_get(
.map(Ok)
.unwrap_or_else(|| accounts_api.any_accounts_exist().map(|b| !b))?;

let wallet_keys = match req.key_index {
Some(id) => sdk.key_manager_api().derive_account_address(id)?,
None => sdk.key_manager_api().next_account_address()?,
};

let acc = accounts_api
.create_account(req.account.as_ref().and_then(|a| a.name()), set_as_default, req.key_id)
.create_account(req.account.as_ref().and_then(|a| a.name()), set_as_default, wallet_keys)
.map_err(|e| {
if e.is_name_exists_error() {
invalid_request(e)
Expand Down Expand Up @@ -237,14 +246,12 @@ pub async fn handle_list(
let sdk = context.wallet_sdk();
let accounts = sdk.accounts_api().get_many(req.offset, req.limit)?;
let total = sdk.accounts_api().count()?;
let km = sdk.key_manager_api();
let accounts = accounts
.into_iter()
.map(|a| {
let account_addr = km.derive_account_address(a.key_index)?;
Ok(AccountInfo {
account: a,
address: account_addr.address.to_byte_type(),
account: a.account,
address: a.address,
})
})
.collect::<Result<_, anyhow::Error>>()?;
Expand All @@ -265,7 +272,7 @@ pub async fn handle_get_balances(
if req.refresh {
context
.account_monitor()
.refresh_account(*account.component_address())
.refresh_account_with_utxos(*account.component_address())
.await?;
}
let vaults = sdk.accounts_api().get_vaults_by_account(account.component_address())?;
Expand Down Expand Up @@ -410,6 +417,10 @@ pub async fn handle_claim_burn(
let accounts_api = sdk.accounts_api();
let account = get_account(&account, &accounts_api)?;

let account_owner_key_id = account
.owner_key_id()
.ok_or_else(|| invalid_params("account", Some("cannot claim burn to an account without an owner key")))?;

let network = sdk.config_api().get_network()?;
let claim_nonce_keypair = sdk
.key_manager_api()
Expand Down Expand Up @@ -466,26 +477,28 @@ pub async fn handle_claim_burn(
})?;

let (nonce, output_public_nonce) = RistrettoPublicKey::random_keypair(&mut OsRng);
let account_owner = sdk.key_manager_api().derive_account_key_pair(account.key_index())?;
let view_only = sdk.key_manager_api().derive_view_only_keypair(account.key_index())?;
let account_owner = sdk.key_manager_api().get_account_owner_key(account_owner_key_id)?;
let account_owner_public_key = account_owner.to_public_key();
let view_only = sdk.key_manager_api().get_view_only_key(account.view_only_key_id())?;
let view_only_public_key = view_only.to_public_key();
// NOTE: the confidential encryption format and the bullet proofs currently do not support amounts larger than
// u64::MAX. Apart from it being insane/basically impossible to have that much XTR in a single UTXO, the L1 emission
// will reach this much in many thousands of years.
let encrypted_data =
sdk.stealth_crypto_api()
.encrypt_value_and_mask(final_amount_u64, &mask.key, &view_only.public_key, &nonce)?;
.encrypt_value_and_mask(final_amount_u64, &mask.key, &view_only_public_key, &nonce)?;

let tag = sdk.stealth_crypto_api().derive_stealth_output_tag(
network,
&nonce,
&view_only.public_key,
&view_only_public_key,
&STEALTH_TARI_RESOURCE_ADDRESS,
);

// Create stealth address - used during spend time
let stealth_output_owner_public_key =
sdk.stealth_crypto_api()
.derive_stealth_owner_public_key(network, &account_owner.public_key, &nonce);
.derive_stealth_owner_public_key(network, &account_owner_public_key, &nonce);

let output_statement = UnblindedStealthOutputStatement {
statement: UnblindedOutputStatement {
Expand Down Expand Up @@ -557,6 +570,13 @@ pub async fn handle_create_free_test_coins(
.optional()?
.ok_or_else(|| not_found(format!("Account with name or address '{}' not found", account,)))?;

let account_owner_key_id = account.owner_key_id().ok_or_else(|| {
invalid_params(
"account",
Some("cannot create free test coins for an account without an owner key"),
)
})?;

info!(
target: LOG_TARGET,
"💰️ Creating free test coins for account: {} with amount: {} and max fee: {}",
Expand Down Expand Up @@ -602,7 +622,7 @@ pub async fn handle_create_free_test_coins(
);
}

let account_secret_key = sdk.key_manager_api().derive_account_key(account.key_index())?;
let account_owner_key = sdk.key_manager_api().get_account_owner_key(account_owner_key_id)?;

let transaction = context
.transaction_builder()
Expand All @@ -623,7 +643,7 @@ pub async fn handle_create_free_test_coins(
.call_method(*account.component_address(), "pay_fee", args![max_fee])
})
.with_inputs(inputs.into_iter().map(|input| input.into_unversioned()))
.build_and_seal(&account_secret_key.key);
.build_and_seal(&account_owner_key.secret);

info!(
target: LOG_TARGET,
Expand Down Expand Up @@ -694,6 +714,10 @@ pub async fn handle_transfer(

let (account, mut inputs) = get_account_with_inputs(req.account.as_ref(), &sdk)?;

let account_owner_key_id = account
.owner_key_id()
.ok_or_else(|| invalid_params("account", Some("cannot transfer from an account without an owner key")))?;

// get the source account component address
let source_account_address = *account.component_address();

Expand Down Expand Up @@ -778,7 +802,7 @@ pub async fn handle_transfer(

// build the transaction
let max_fee = req.max_fee.unwrap_or(DEFAULT_FEE);
let account_secret_key = sdk.key_manager_api().derive_account_key(account.key_index())?;
let account_owner_key = sdk.key_manager_api().get_account_owner_key(account_owner_key_id)?;

let transaction = builder
.with_dry_run(req.dry_run)
Expand Down Expand Up @@ -807,7 +831,7 @@ pub async fn handle_transfer(
}
})
.with_inputs(inputs.into_iter().map(|req| req.into_unversioned()))
.build_and_seal(&account_secret_key.key);
.build_and_seal(&account_owner_key.secret);

// If dry run we can return the result immediately
if req.dry_run {
Expand Down Expand Up @@ -972,7 +996,7 @@ pub async fn handle_associate_stealth_resource(

context
.account_monitor()
.refresh_account(*account.component_address())
.refresh_account_with_utxos(*account.component_address())
.await?;

Ok(AccountsAssociateStealthResourceResponse {})
Expand Down
10 changes: 7 additions & 3 deletions applications/tari_walletd/src/handlers/confidential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ pub async fn handle_create_transfer_proof(
}

let account = get_account_or_default(req.account.as_ref(), &sdk.accounts_api())?;
let account_owner_key_id = account
.owner_key_id()
.ok_or_else(|| invalid_request("Account does not have an owner key"))?;
let vault = sdk
.accounts_api()
.get_vault_by_resource(account.component_address(), &req.resource_address)?;
Expand Down Expand Up @@ -83,7 +86,7 @@ pub async fn handle_create_transfer_proof(
// TODO: Any errors from here need to unlock the outputs, ideally just roll back (refactor required but doable).

// TODO: Wrap up key/encrypted data handling in the wallet SDK
let account_secret = sdk.key_manager_api().derive_account_key(account.key_index())?;
let account_key = sdk.key_manager_api().get_account_owner_key(account_owner_key_id)?;
let output_mask = sdk.key_manager_api().next_key(KeyBranch::ConfidentialMask)?;
let (_, public_nonce) = RistrettoPublicKey::random_keypair(&mut OsRng);

Expand All @@ -98,7 +101,7 @@ pub async fn handle_create_transfer_proof(
amount_u64,
&output_mask.key,
&public_nonce,
&account_secret.key,
&account_key.secret,
)?;

let resource = sdk.substate_api().fetch_resource(req.resource_address).await?;
Expand Down Expand Up @@ -157,7 +160,8 @@ pub async fn handle_create_transfer_proof(
.to_byte_type(),
value: change_amount,
sender_public_nonce: Some(public_nonce.to_byte_type()),
encryption_secret_key_index: change_mask.key_index,
view_only_key_id: account.view_only_key_id(),
owner_key_id: account.owner_key_id(),
encrypted_data: encrypted_data.clone(),
public_asset_tag: None,
status: OutputStatus::LockedUnconfirmed,
Expand Down
Loading
Loading