From dc20a8ce95d1e7d9c1832fc48eb805255c02d809 Mon Sep 17 00:00:00 2001 From: BHouwens Date: Tue, 30 Apr 2024 13:47:53 +0200 Subject: [PATCH] User wallet fix for miner DBs; Adding outgoing transactions --- src/api/handlers.rs | 14 ++++---- src/api/routes.rs | 10 +++--- src/api/tests.rs | 12 +++++-- src/bin/node_settings_mainnet.toml | 2 +- src/user.rs | 24 ++++++++++--- src/wallet/fund_store.rs | 4 +-- src/wallet/mod.rs | 56 ++++++++++++++++++++++++++++-- 7 files changed, 99 insertions(+), 23 deletions(-) diff --git a/src/api/handlers.rs b/src/api/handlers.rs index 927e7824..fa64ba13 100644 --- a/src/api/handlers.rs +++ b/src/api/handlers.rs @@ -404,18 +404,20 @@ pub async fn get_total_supply( } /// GET The last constructed transaction -pub async fn get_last_constructed_tx( +pub async fn get_outgoing_txs( route: &'static str, db: WalletDb, call_id: String, ) -> Result { let r = CallResponse::new(route, &call_id); - let last_tx = db.get_last_constructed_tx(); - r.into_ok( - "Successfully fetched last constructed transaction", - json_serialize_embed(last_tx), - ) + match db.get_outgoing_txs() { + Ok(tx) => r.into_ok( + "Successfully fetched last constructed transaction", + json_serialize_embed(tx), + ), + Err(_e) => r.into_err_internal(ApiErrorType::CannotAccessWallet), + } } //======= POST HANDLERS =======// diff --git a/src/api/routes.rs b/src/api/routes.rs index ea7642b7..4b2c31c0 100644 --- a/src/api/routes.rs +++ b/src/api/routes.rs @@ -291,14 +291,14 @@ pub fn get_shared_config( } /// GET last constructed transaction -pub fn get_last_constructed_tx( +pub fn get_outgoing_txs( dp: &mut DbgPaths, db: WalletDb, routes_pow: RoutesPoWInfo, api_keys: ApiKeys, cache: ReplyCache, ) -> impl Filter + Clone { - let route = "last_constructed_tx"; + let route = "outgoing_transactions"; warp_path(dp, route) .and(warp::get()) .and(auth_request(routes_pow, api_keys)) @@ -308,7 +308,7 @@ pub fn get_last_constructed_tx( map_api_res_and_cache( call_id.clone(), cache, - handlers::get_last_constructed_tx(route, db, call_id), + handlers::get_outgoing_txs(route, db, call_id), ) }) .with(get_cors()) @@ -841,7 +841,7 @@ pub fn user_node_routes( api_keys.clone(), cache.clone(), ) - .or(get_last_constructed_tx( + .or(get_outgoing_txs( dp, db.clone(), routes_pow_info.clone(), @@ -1198,7 +1198,7 @@ pub fn miner_node_with_user_routes( api_keys.clone(), cache.clone(), )) - .or(get_last_constructed_tx( + .or(get_outgoing_txs( dp, db.clone(), routes_pow_info.clone(), diff --git a/src/api/tests.rs b/src/api/tests.rs index 88c07b55..5ccc2c84 100644 --- a/src/api/tests.rs +++ b/src/api/tests.rs @@ -1765,9 +1765,15 @@ async fn test_post_update_running_total() { let ks = to_api_keys(Default::default()); let cache = create_new_cache(CACHE_LIVE_TIME); - let filter = - routes::update_running_total(&mut dp(), self_node.clone(), db, Default::default(), ks, cache) - .recover(handle_rejection); + let filter = routes::update_running_total( + &mut dp(), + self_node.clone(), + db, + Default::default(), + ks, + cache, + ) + .recover(handle_rejection); let res = request.reply(&filter).await; // diff --git a/src/bin/node_settings_mainnet.toml b/src/bin/node_settings_mainnet.toml index a9775c5c..f79a5f54 100644 --- a/src/bin/node_settings_mainnet.toml +++ b/src/bin/node_settings_mainnet.toml @@ -27,4 +27,4 @@ address = "52.40.82.170:8080" address = "52.27.248.13:12340" [[user_nodes]] -address = "127.0.0.1:12342" +address = "127.0.0.1:12349" diff --git a/src/user.rs b/src/user.rs index a5709dad..fec208c7 100644 --- a/src/user.rs +++ b/src/user.rs @@ -24,7 +24,8 @@ use tw_chain::primitives::block::Block; use tw_chain::primitives::druid::{DdeValues, DruidExpectation}; use tw_chain::primitives::transaction::{GenesisTxHashSpec, Transaction, TxIn, TxOut}; use tw_chain::utils::transaction_utils::{ - construct_item_create_tx, construct_rb_payments_send_tx, construct_rb_receive_payment_tx, construct_tx_core, construct_tx_ins_address, update_input_signatures, ReceiverInfo + construct_item_create_tx, construct_rb_payments_send_tx, construct_rb_receive_payment_tx, + construct_tx_core, construct_tx_ins_address, update_input_signatures, ReceiverInfo, }; use std::{collections::BTreeMap, error::Error, fmt, future::Future, net::SocketAddr}; @@ -1725,8 +1726,15 @@ pub fn make_rb_payment_item_tx_and_response( genesis_hash: None, }; - let rb_receive_tx = - construct_rb_receive_payment_tx(tx_ins, tx_outs, None, sender_address, 0, dde_values, &BTreeMap::new()); + let rb_receive_tx = construct_rb_receive_payment_tx( + tx_ins, + tx_outs, + None, + sender_address, + 0, + dde_values, + &BTreeMap::new(), + ); let rb_payment_response = RbPaymentResponseData { receiver_address, @@ -1771,7 +1779,15 @@ pub fn make_rb_payment_send_transaction( asset: sender_asset, }; - construct_rb_payments_send_tx(tx_ins, tx_outs, None, receiver, 0, druid_values, &BTreeMap::new()) + construct_rb_payments_send_tx( + tx_ins, + tx_outs, + None, + receiver, + 0, + druid_values, + &BTreeMap::new(), + ) } fn make_transaction_gen(setup: UserAutoGenTxSetup) -> Option { diff --git a/src/wallet/fund_store.rs b/src/wallet/fund_store.rs index 6b041b4f..3dea0725 100644 --- a/src/wallet/fund_store.rs +++ b/src/wallet/fund_store.rs @@ -45,14 +45,14 @@ impl FundStore { pub fn transactions(&self) -> &BTreeMap { &self.transactions } - + pub fn reset(&mut self) { self.running_total = Default::default(); self.transactions = Default::default(); self.transaction_pages = vec![BTreeMap::new()]; self.spent_transactions = Default::default(); } - + /// Filters out locked coinbase transactions, updating the running total. /// /// Returns amount of filtered out coinbase transactions due to locktime diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs index 11a3278c..8533a2d8 100644 --- a/src/wallet/mod.rs +++ b/src/wallet/mod.rs @@ -33,6 +33,9 @@ pub const LOCKED_COINBASE_KEY: &str = "LockedCoinbaseKey"; /// Storage key for a &[u8] of the word 'MasterKeyStore' pub const MASTER_KEY_STORE_KEY: &str = "MasterKeyStore"; +/// Storage key for all outgoing transactions +pub const OUTGOING_TXS_KEY: &str = "OutgoingTxs"; + pub const DB_SPEC: SimpleDbSpec = SimpleDbSpec { db_path: WALLET_PATH, suffix: "", @@ -60,6 +63,7 @@ pub enum WalletDbError { InsufficientFundsError, MasterKeyRetrievalError, MasterKeyMissingError, + OutgoingTxMissingError, } impl fmt::Display for WalletDbError { @@ -74,6 +78,7 @@ impl fmt::Display for WalletDbError { Self::InsufficientFundsError => write!(f, "InsufficientFundsError"), Self::MasterKeyRetrievalError => write!(f, "MasterKeyRetrievalError"), Self::MasterKeyMissingError => write!(f, "MasterKeyMissingError"), + Self::OutgoingTxMissingError => write!(f, "OutgoingTxMissingError"), } } } @@ -90,6 +95,7 @@ impl error::Error for WalletDbError { Self::InsufficientFundsError => None, Self::MasterKeyRetrievalError => None, Self::MasterKeyMissingError => None, + Self::OutgoingTxMissingError => None, } } } @@ -255,6 +261,14 @@ impl WalletDb { self.locked_coinbase.lock().await.clone() } + /// Gets all outgoing transactions + pub fn get_outgoing_txs(&self) -> Result> { + let db = self.db.clone(); + let db = db.lock().unwrap(); + + get_outgoing_txs(&db) + } + /// Builds a key material map for a given set of transaction inputs /// /// ### Arguments @@ -546,10 +560,12 @@ impl WalletDb { debug!("Usable outpoints: {:?}", usable_outpoints); debug!("Number of usable outpoints: {}", usable_outpoints.len()); let existing_tx = fund_store.transactions().clone(); - debug!("Number of existing transactions: {:?}", existing_tx.len()); if usable_outpoints.len() == existing_tx.len() { fund_store.reset(); - debug!("Current running total after reset: {:?}", fund_store.running_total()); + debug!( + "Current running total after reset: {:?}", + fund_store.running_total() + ); } else { for (out_p, _) in &existing_tx { if !usable_outpoints.contains(out_p) { @@ -696,6 +712,14 @@ impl WalletDb { .save_usable_payments_to_wallet(payments, b_num, false) .await .unwrap(); + + let mut db = self.db.lock().unwrap(); + let mut batch = db.batch_writer(); + save_outgoing_tx_to_wallet(&db, &mut batch, (hash, transaction)); + + let batch = batch.done(); + db.write(batch).unwrap(); + tracing::debug!("store_payment_transactions: {:?}", our_payments); } @@ -1063,6 +1087,34 @@ pub fn save_transaction_to_wallet( db.put_cf(DB_COL_DEFAULT, &key, &input); } +pub fn save_outgoing_tx_to_wallet( + db: &SimpleDb, + batch: &mut SimpleDbWriteBatch, + outgoing_tx: (String, Transaction), +) { + match get_outgoing_txs(db) { + Ok(mut outgoing_txs) => { + outgoing_txs.insert(outgoing_tx.0, outgoing_tx.1); + let store = serialize(&outgoing_txs).unwrap(); + batch.put_cf(DB_COL_DEFAULT, OUTGOING_TXS_KEY, &store); + } + Err(_) => { + let mut outgoing_txs = BTreeMap::new(); + outgoing_txs.insert(outgoing_tx.0, outgoing_tx.1); + let store = serialize(&outgoing_txs).unwrap(); + batch.put_cf(DB_COL_DEFAULT, OUTGOING_TXS_KEY, &store); + } + } +} + +pub fn get_outgoing_txs(db: &SimpleDb) -> Result> { + let store = db.get_cf(DB_COL_DEFAULT, OUTGOING_TXS_KEY)?; + let store = store.ok_or(WalletDbError::OutgoingTxMissingError)?; + let outgoing_tx: BTreeMap = deserialize(&store)?; + + Ok(outgoing_tx) +} + // Set a new master key store pub fn set_new_master_key_store( batch: &mut SimpleDbWriteBatch,