Skip to content
Draft
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
74 changes: 28 additions & 46 deletions src/backend_task/core/create_asset_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,31 @@ impl AppContext {
) -> Result<BackendTaskSuccessResult, TaskError> {
let amount_duffs = amount / CREDITS_PER_DUFF;

let (asset_lock_transaction, _private_key, _change_address, _used_utxos) = {
let (asset_lock_transaction, _private_key, _change_address, used_utxos, wallet_seed_hash) = {
let mut wallet_guard = wallet.write()?;
let seed_hash = wallet_guard.seed_hash();

wallet_guard
let (tx, key, addr, utxos) = wallet_guard
.registration_asset_lock_transaction(
self,
self.network,
amount_duffs,
allow_take_fee_from_amount,
identity_index,
)
.map_err(|e| TaskError::AssetLockTransactionBuildFailed { detail: e })?
.map_err(|e| TaskError::AssetLockTransactionBuildFailed { detail: e })?;
(tx, key, addr, utxos, seed_hash)
};

let tx_id = asset_lock_transaction.txid();

{
let mut proofs = self.transactions_waiting_for_finality.lock()?;
proofs.insert(tx_id, None);
}

if let Err(e) = self
.broadcast_raw_transaction(&asset_lock_transaction)
.await
{
if let Ok(mut proofs) = self.transactions_waiting_for_finality.lock() {
proofs.remove(&tx_id);
} else {
tracing::warn!(
"Failed to clean up finality tracking for tx {tx_id}: Mutex poisoned"
);
}
return Err(e);
}
let tx_id = self
.broadcast_and_commit_asset_lock(
&asset_lock_transaction,
amount_duffs,
&wallet_seed_hash,
&wallet,
&used_utxos,
)
.await?;

Ok(BackendTaskSuccessResult::Message(format!(
"Asset lock transaction broadcast successfully. TX ID: {}",
Expand All @@ -67,10 +58,11 @@ impl AppContext {
) -> Result<BackendTaskSuccessResult, TaskError> {
let amount_duffs = amount / CREDITS_PER_DUFF;

let (asset_lock_transaction, _private_key, _change_address, _used_utxos) = {
let (asset_lock_transaction, _private_key, _change_address, used_utxos, wallet_seed_hash) = {
let mut wallet_guard = wallet.write()?;
let seed_hash = wallet_guard.seed_hash();

wallet_guard
let (tx, key, addr, utxos) = wallet_guard
.top_up_asset_lock_transaction(
self,
self.network,
Expand All @@ -79,29 +71,19 @@ impl AppContext {
identity_index,
top_up_index,
)
.map_err(|e| TaskError::AssetLockTransactionBuildFailed { detail: e })?
.map_err(|e| TaskError::AssetLockTransactionBuildFailed { detail: e })?;
(tx, key, addr, utxos, seed_hash)
};

let tx_id = asset_lock_transaction.txid();

{
let mut proofs = self.transactions_waiting_for_finality.lock()?;
proofs.insert(tx_id, None);
}

if let Err(e) = self
.broadcast_raw_transaction(&asset_lock_transaction)
.await
{
if let Ok(mut proofs) = self.transactions_waiting_for_finality.lock() {
proofs.remove(&tx_id);
} else {
tracing::warn!(
"Failed to clean up finality tracking for tx {tx_id}: Mutex poisoned"
);
}
return Err(e);
}
let tx_id = self
.broadcast_and_commit_asset_lock(
&asset_lock_transaction,
amount_duffs,
&wallet_seed_hash,
&wallet,
&used_utxos,
)
.await?;

Ok(BackendTaskSuccessResult::Message(format!(
"Asset lock transaction broadcast successfully. TX ID: {}",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::backend_task::BackendTaskSuccessResult;
use crate::backend_task::error::TaskError;
use crate::context::AppContext;
use crate::model::wallet::WalletSeedHash;
use crate::model::wallet::{AssetLockUsage, WalletSeedHash};
use dash_sdk::dpp::address_funds::PlatformAddress;
use dash_sdk::dpp::balances::credits::CREDITS_PER_DUFF;
use std::sync::Arc;
Expand Down Expand Up @@ -50,12 +50,17 @@ impl AppContext {

let mut wallet = wallet_arc.write()?;

let usage = AssetLockUsage::PlatformAddressFunding;
let funding_index = wallet.next_generic_funding_index(self.network, usage);

// Try to create the asset lock transaction, reload UTXOs if needed
match wallet.generic_asset_lock_transaction(
self,
self.network,
asset_lock_amount,
allow_take_fee_from_amount,
usage,
funding_index,
) {
Ok((tx, private_key, address, _change, utxos)) => (tx, private_key, address, utxos),
Err(e) => {
Expand All @@ -73,6 +78,8 @@ impl AppContext {
self.network,
asset_lock_amount,
allow_take_fee_from_amount,
usage,
funding_index,
)
.map_err(|e| TaskError::AssetLockTransactionBuildFailed { detail: e })?;
(tx, private_key, address, utxos)
Expand Down
18 changes: 10 additions & 8 deletions src/model/wallet/asset_lock_transaction.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::context::AppContext;
use crate::model::wallet::Wallet;
use crate::model::wallet::{AssetLockUsage, Wallet};
use dash_sdk::dashcore_rpc::dashcore::key::Secp256k1;
use dash_sdk::dpp::dashcore::secp256k1::Message;
use dash_sdk::dpp::dashcore::sighash::SighashCache;
Expand Down Expand Up @@ -221,15 +221,21 @@ impl Wallet {
)
}

/// Create an asset lock transaction with a randomly generated one-time key.
/// Create an asset lock transaction with a deterministic HD-derived key.
/// This is used for generic platform address funding (not identity-specific).
///
/// The key is derived from `m/9'/coin_type'/5'/sub_feature'/index'` where
/// the sub-feature is determined by the `AssetLockUsage` parameter per
/// DIP-9 Feature 5' assignments.
#[allow(clippy::type_complexity)]
pub fn generic_asset_lock_transaction(
&mut self,
app_context: &AppContext,
network: Network,
amount: u64,
allow_take_fee_from_amount: bool,
usage: AssetLockUsage,
funding_index: u32,
) -> Result<
(
Transaction,
Expand All @@ -240,15 +246,11 @@ impl Wallet {
),
String,
> {
use bip39::rand::rngs::OsRng;

// Generate a random private key for the asset lock
let private_key =
self.generic_asset_lock_ecdsa_private_key(app_context, network, usage, funding_index)?;
let secp = Secp256k1::new();
let (secret_key, _) = secp.generate_keypair(&mut OsRng);
let private_key = PrivateKey::new(secret_key, network);
let public_key = private_key.public_key(&secp);

// The asset lock address is where the proof will be tied to
let asset_lock_address = Address::p2pkh(&public_key, network);

let (tx, returned_private_key, change_address, used_utxos) = self
Expand Down
Loading