2022-06-08 05:48:16 -07:00
|
|
|
// Sync
|
|
|
|
|
|
|
|
use crate::coinconfig::CoinConfig;
|
2022-09-05 08:05:55 -07:00
|
|
|
use crate::db::PlainNote;
|
2022-06-08 05:48:16 -07:00
|
|
|
use crate::scan::AMProgressCallback;
|
2022-09-05 08:05:55 -07:00
|
|
|
use crate::{AccountData, BlockId, CTree, CompactTxStreamerClient, DbAdapter};
|
2022-06-08 05:48:16 -07:00
|
|
|
use std::sync::Arc;
|
|
|
|
use tokio::sync::Mutex;
|
|
|
|
use tonic::transport::Channel;
|
|
|
|
use tonic::Request;
|
2022-09-04 04:19:49 -07:00
|
|
|
use zcash_primitives::sapling::Note;
|
2022-06-08 05:48:16 -07:00
|
|
|
|
|
|
|
const DEFAULT_CHUNK_SIZE: u32 = 100_000;
|
|
|
|
|
|
|
|
pub async fn coin_sync(
|
|
|
|
coin: u8,
|
|
|
|
get_tx: bool,
|
|
|
|
anchor_offset: u32,
|
2022-07-30 16:11:58 -07:00
|
|
|
max_cost: u32,
|
2022-06-08 05:48:16 -07:00
|
|
|
progress_callback: impl Fn(u32) + Send + 'static,
|
2022-08-30 07:00:15 -07:00
|
|
|
cancel: &'static std::sync::Mutex<bool>,
|
2022-06-08 05:48:16 -07:00
|
|
|
) -> anyhow::Result<()> {
|
|
|
|
let cb = Arc::new(Mutex::new(progress_callback));
|
2022-07-21 18:08:29 -07:00
|
|
|
coin_sync_impl(
|
|
|
|
coin,
|
|
|
|
get_tx,
|
|
|
|
DEFAULT_CHUNK_SIZE,
|
|
|
|
anchor_offset,
|
2022-07-30 16:11:58 -07:00
|
|
|
max_cost,
|
|
|
|
cb.clone(),
|
|
|
|
cancel,
|
|
|
|
)
|
|
|
|
.await?;
|
|
|
|
coin_sync_impl(
|
|
|
|
coin,
|
|
|
|
get_tx,
|
|
|
|
DEFAULT_CHUNK_SIZE,
|
|
|
|
0,
|
|
|
|
u32::MAX,
|
2022-07-21 18:08:29 -07:00
|
|
|
cb.clone(),
|
|
|
|
cancel,
|
|
|
|
)
|
|
|
|
.await?;
|
2022-06-08 05:48:16 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn coin_sync_impl(
|
|
|
|
coin: u8,
|
|
|
|
get_tx: bool,
|
|
|
|
chunk_size: u32,
|
|
|
|
target_height_offset: u32,
|
2022-07-30 16:11:58 -07:00
|
|
|
max_cost: u32,
|
2022-06-08 05:48:16 -07:00
|
|
|
progress_callback: AMProgressCallback,
|
2022-08-30 07:00:15 -07:00
|
|
|
cancel: &'static std::sync::Mutex<bool>,
|
2022-06-08 05:48:16 -07:00
|
|
|
) -> anyhow::Result<()> {
|
|
|
|
let c = CoinConfig::get(coin);
|
|
|
|
crate::scan::sync_async(
|
|
|
|
c.coin_type,
|
|
|
|
chunk_size,
|
|
|
|
get_tx,
|
2022-07-21 18:08:29 -07:00
|
|
|
c.db_path.as_ref().unwrap(),
|
2022-06-08 05:48:16 -07:00
|
|
|
target_height_offset,
|
2022-07-30 16:11:58 -07:00
|
|
|
max_cost,
|
2022-06-08 05:48:16 -07:00
|
|
|
progress_callback,
|
2022-07-21 18:08:29 -07:00
|
|
|
cancel,
|
|
|
|
c.lwd_url.as_ref().unwrap(),
|
2022-06-08 05:48:16 -07:00
|
|
|
)
|
|
|
|
.await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn get_latest_height() -> anyhow::Result<u32> {
|
|
|
|
let c = CoinConfig::get_active();
|
|
|
|
let mut client = c.connect_lwd().await?;
|
|
|
|
let last_height = crate::chain::get_latest_height(&mut client).await?;
|
|
|
|
Ok(last_height)
|
|
|
|
}
|
|
|
|
|
2022-06-10 02:16:00 -07:00
|
|
|
pub fn get_synced_height() -> anyhow::Result<u32> {
|
|
|
|
let c = CoinConfig::get_active();
|
|
|
|
let db = c.db()?;
|
|
|
|
db.get_last_sync_height().map(|h| h.unwrap_or(0))
|
|
|
|
}
|
|
|
|
|
2022-06-08 05:48:16 -07:00
|
|
|
pub async fn skip_to_last_height(coin: u8) -> anyhow::Result<()> {
|
2022-07-08 01:27:39 -07:00
|
|
|
let c = CoinConfig::get(coin);
|
2022-06-08 05:48:16 -07:00
|
|
|
let mut client = c.connect_lwd().await?;
|
|
|
|
let last_height = crate::chain::get_latest_height(&mut client).await?;
|
2022-07-08 01:27:39 -07:00
|
|
|
fetch_and_store_tree_state(coin, &mut client, last_height).await?;
|
2022-06-08 05:48:16 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-09-05 08:05:55 -07:00
|
|
|
// if exact = true, do not snap the height to a pre existing checkpoint
|
|
|
|
// and get the tree_state from the server
|
|
|
|
// this option is used when we rescan from a given height
|
|
|
|
// We ignore any transaction that occurred before
|
2022-09-06 19:38:16 -07:00
|
|
|
pub async fn rewind_to(height: u32) -> anyhow::Result<u32> {
|
2022-06-08 05:48:16 -07:00
|
|
|
let c = CoinConfig::get_active();
|
2022-09-06 19:38:16 -07:00
|
|
|
let height = c.db()?.trim_to_height(height)?;
|
2022-09-02 08:11:50 -07:00
|
|
|
Ok(height)
|
2022-06-08 05:48:16 -07:00
|
|
|
}
|
|
|
|
|
2022-09-06 19:38:16 -07:00
|
|
|
pub async fn rescan_from(height: u32) -> anyhow::Result<()> {
|
|
|
|
let c = CoinConfig::get_active();
|
|
|
|
c.db()?.truncate_sync_data()?;
|
|
|
|
let mut client = c.connect_lwd().await?;
|
|
|
|
fetch_and_store_tree_state(c.coin, &mut client, height).await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-06-08 05:48:16 -07:00
|
|
|
async fn fetch_and_store_tree_state(
|
2022-07-08 01:27:39 -07:00
|
|
|
coin: u8,
|
2022-06-08 05:48:16 -07:00
|
|
|
client: &mut CompactTxStreamerClient<Channel>,
|
|
|
|
height: u32,
|
|
|
|
) -> anyhow::Result<()> {
|
2022-07-08 01:27:39 -07:00
|
|
|
let c = CoinConfig::get(coin);
|
2022-06-08 05:48:16 -07:00
|
|
|
let block_id = BlockId {
|
|
|
|
height: height as u64,
|
|
|
|
hash: vec![],
|
|
|
|
};
|
|
|
|
let block = client.get_block(block_id.clone()).await?.into_inner();
|
|
|
|
let tree_state = client
|
|
|
|
.get_tree_state(Request::new(block_id))
|
|
|
|
.await?
|
|
|
|
.into_inner();
|
2022-06-11 05:29:14 -07:00
|
|
|
let tree = CTree::read(&*hex::decode(&tree_state.sapling_tree)?)?;
|
2022-07-12 00:28:58 -07:00
|
|
|
let db = c.db()?;
|
|
|
|
DbAdapter::store_block(&db.connection, height, &block.hash, block.time, &tree)?;
|
2022-06-08 05:48:16 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn get_activation_date() -> anyhow::Result<u32> {
|
|
|
|
let c = CoinConfig::get_active();
|
|
|
|
let mut client = c.connect_lwd().await?;
|
|
|
|
let date_time = crate::chain::get_activation_date(c.chain.network(), &mut client).await?;
|
|
|
|
Ok(date_time)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn get_block_by_time(time: u32) -> anyhow::Result<u32> {
|
|
|
|
let c = CoinConfig::get_active();
|
|
|
|
let mut client = c.connect_lwd().await?;
|
|
|
|
let date_time = crate::chain::get_block_by_time(c.chain.network(), &mut client, time).await?;
|
|
|
|
Ok(date_time)
|
|
|
|
}
|
2022-09-04 04:19:49 -07:00
|
|
|
|
2022-09-05 08:05:55 -07:00
|
|
|
pub fn trial_decrypt(
|
|
|
|
height: u32,
|
|
|
|
cmu: &[u8],
|
|
|
|
epk: &[u8],
|
|
|
|
ciphertext: &[u8],
|
|
|
|
) -> anyhow::Result<Option<Note>> {
|
2022-09-04 04:19:49 -07:00
|
|
|
let c = CoinConfig::get_active();
|
|
|
|
let AccountData { fvk, .. } = c.db().unwrap().get_account_info(c.id_account)?;
|
2022-09-05 08:05:55 -07:00
|
|
|
let note =
|
|
|
|
crate::scan::trial_decrypt_one(c.chain.network(), height, &fvk, cmu, epk, ciphertext)?;
|
2022-09-04 04:19:49 -07:00
|
|
|
Ok(note)
|
|
|
|
}
|