Skip to content

Commit

Permalink
Update json file after removing outdated transactions #1321 (#1332)
Browse files Browse the repository at this point in the history
* Update json file after removing outdated transactions

* Remove commented out debug code

* Remove save_transaction_history and extend save_history_to_file instead

* Add function for transaction comparison

* Handle transactions with 0 block height separately while sorting

* Fix formatting
  • Loading branch information
caglaryucekaya authored Jul 11, 2022
1 parent d7e8c2b commit ce32ab8
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 53 deletions.
20 changes: 1 addition & 19 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ use secp256k1::PublicKey;
use serde_json::{self as json, Value as Json};
use serialization::{CompactInteger, Serializable, Stream};
use sha3::{Digest, Keccak256};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::ops::Deref;
use std::path::PathBuf;
Expand Down Expand Up @@ -1782,15 +1781,6 @@ impl EthCoin {
};

existing_history.push(details);
existing_history.sort_unstable_by(|a, b| {
if a.block_height == 0 {
Ordering::Less
} else if b.block_height == 0 {
Ordering::Greater
} else {
b.block_height.cmp(&a.block_height)
}
});

if let Err(e) = self.save_history_to_file(ctx, existing_history.clone()).compat().await {
ctx.log.log(
Expand Down Expand Up @@ -2157,15 +2147,7 @@ impl EthCoin {
};

existing_history.push(details);
existing_history.sort_unstable_by(|a, b| {
if a.block_height == 0 {
Ordering::Less
} else if b.block_height == 0 {
Ordering::Greater
} else {
b.block_height.cmp(&a.block_height)
}
});

if let Err(e) = self.save_history_to_file(ctx, existing_history).compat().await {
ctx.log.log(
"",
Expand Down
22 changes: 20 additions & 2 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use mm2_number::MmNumber;
use rpc::v1::types::{Bytes as BytesJson, H256 as H256Json};
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::{self as json, Value as Json};
use std::cmp::Ordering;
use std::collections::hash_map::{HashMap, RawEntryMut};
use std::fmt;
use std::num::NonZeroUsize;
Expand Down Expand Up @@ -3003,14 +3004,16 @@ where
}

#[cfg(target_arch = "wasm32")]
fn save_history_to_file_impl<T>(coin: &T, ctx: &MmArc, history: Vec<TransactionDetails>) -> TxHistoryFut<()>
fn save_history_to_file_impl<T>(coin: &T, ctx: &MmArc, mut history: Vec<TransactionDetails>) -> TxHistoryFut<()>
where
T: MmCoin + MarketCoinOps + ?Sized,
{
let ctx = ctx.clone();
let ticker = coin.ticker().to_owned();
let my_address = try_f!(coin.my_address().map_to_mm(TxHistoryError::InternalError));

history.sort_unstable_by(compare_transactions);

let fut = async move {
let coins_ctx = CoinsContext::from_ctx(&ctx).unwrap();
let db = coins_ctx.tx_history_db().await?;
Expand All @@ -3021,13 +3024,15 @@ where
}

#[cfg(not(target_arch = "wasm32"))]
fn save_history_to_file_impl<T>(coin: &T, ctx: &MmArc, history: Vec<TransactionDetails>) -> TxHistoryFut<()>
fn save_history_to_file_impl<T>(coin: &T, ctx: &MmArc, mut history: Vec<TransactionDetails>) -> TxHistoryFut<()>
where
T: MmCoin + MarketCoinOps + ?Sized,
{
let history_path = coin.tx_history_path(ctx);
let tmp_file = format!("{}.tmp", history_path.display());

history.sort_unstable_by(compare_transactions);

let fut = async move {
let content = json::to_vec(&history).map_to_mm(|e| TxHistoryError::ErrorSerializing(e.to_string()))?;

Expand All @@ -3048,3 +3053,16 @@ where
};
Box::new(fut.boxed().compat())
}

fn compare_transactions(a: &TransactionDetails, b: &TransactionDetails) -> Ordering {
// the transactions with block_height == 0 are the most recent so we need to separately handle them while sorting
if a.block_height == b.block_height {
a.internal_id.cmp(&b.internal_id)
} else if a.block_height == 0 {
Ordering::Less
} else if b.block_height == 0 {
Ordering::Greater
} else {
b.block_height.cmp(&a.block_height)
}
}
21 changes: 1 addition & 20 deletions mm2src/coins/qrc20/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use common::jsonrpc_client::JsonRpcErrorType;
use common::mm_metrics::MetricsArc;
use itertools::Itertools;
use script_pubkey::{extract_contract_call_from_script, extract_gas_from_script, ExtractGasEnum};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::io::Cursor;
use utxo_common::{HISTORY_TOO_LARGE_ERROR, HISTORY_TOO_LARGE_ERR_CODE};
Expand Down Expand Up @@ -173,18 +172,11 @@ impl Qrc20Coin {
}

// `history_map` has been updated.
let mut to_write: Vec<TransactionDetails> = history_map
let to_write: Vec<TransactionDetails> = history_map
.iter()
.flat_map(|(_, value)| value)
.map(|(_tx_id, tx)| tx.clone())
.collect();
to_write.sort_unstable_by(|a, b| {
match sort_newest_to_oldest(a.block_height, b.block_height) {
// do not reverse `transfer` events in one transaction
Ordering::Equal => a.internal_id.cmp(&b.internal_id),
ord => ord,
}
});
if let Err(e) = self.save_history_to_file(&ctx, to_write).compat().await {
ctx.log.log(
"",
Expand Down Expand Up @@ -810,17 +802,6 @@ fn is_transferred_to_contract(script_pubkey: &Script) -> bool {
}
}

fn sort_newest_to_oldest(x_height: u64, y_height: u64) -> Ordering {
// the transactions with block_height == 0 are the most recent
if x_height == 0 {
Ordering::Less
} else if y_height == 0 {
Ordering::Greater
} else {
y_height.cmp(&x_height)
}
}

fn is_transfer_event_log(log: &LogEntry) -> bool {
match log.topics.first() {
Some(first_topic) => first_topic == QRC20_TRANSFER_TOPIC,
Expand Down
29 changes: 17 additions & 12 deletions mm2src/coins/utxo/utxo_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,7 @@ where
return;
},
};

let mut history_map: HashMap<H256Json, TransactionDetails> = history
.into_iter()
.filter_map(|tx| {
Expand Down Expand Up @@ -2139,9 +2140,24 @@ where
};

// Remove transactions in the history_map that are not in the requested transaction list anymore
let history_length = history_map.len();
let requested_ids: HashSet<H256Json> = tx_ids.iter().map(|x| x.0).collect();
history_map.retain(|hash, _| requested_ids.contains(hash));

if history_map.len() < history_length {
let to_write: Vec<TransactionDetails> = history_map.iter().map(|(_, value)| value.clone()).collect();
if let Err(e) = coin.save_history_to_file(&ctx, to_write).compat().await {
log_tag!(
ctx,
"",
"tx_history",
"coin" => coin.as_ref().conf.ticker;
fmt = "Error {} on 'save_history_to_file', stop the history loop", e
);
return;
};
}

let mut transactions_left = if tx_ids.len() > history_map.len() {
*coin.as_ref().history_sync_state.lock().unwrap() = HistorySyncState::InProgress(json!({
"transactions_left": tx_ids.len() - history_map.len()
Expand Down Expand Up @@ -2206,18 +2222,7 @@ where
},
}
if updated {
let mut to_write: Vec<TransactionDetails> =
history_map.iter().map(|(_, value)| value.clone()).collect();
// the transactions with block_height == 0 are the most recent so we need to separately handle them while sorting
to_write.sort_unstable_by(|a, b| {
if a.block_height == 0 {
Ordering::Less
} else if b.block_height == 0 {
Ordering::Greater
} else {
b.block_height.cmp(&a.block_height)
}
});
let to_write: Vec<TransactionDetails> = history_map.iter().map(|(_, value)| value.clone()).collect();
if let Err(e) = coin.save_history_to_file(&ctx, to_write).compat().await {
log_tag!(
ctx,
Expand Down

0 comments on commit ce32ab8

Please sign in to comment.