Rescan from given height

This commit is contained in:
Hanh 2022-04-01 13:20:53 +08:00
parent 74bc5be12b
commit 5caecd36a6
2 changed files with 60 additions and 6 deletions

View File

@ -32,6 +32,39 @@ pub async fn get_latest_height(
Ok(block_id.height as u32)
}
pub async fn get_activation_date(network: &Network, client: &mut CompactTxStreamerClient<Channel>) -> anyhow::Result<u32> {
let height = network.activation_height(NetworkUpgrade::Sapling).unwrap();
let time = get_block_date(client, u32::from(height)).await?;
Ok(time)
}
pub async fn get_block_date(client: &mut CompactTxStreamerClient<Channel>, height: u32) -> anyhow::Result<u32> {
let block = client.get_block(Request::new(BlockId { height: height as u64, hash: vec![] })).await?.into_inner();
Ok(block.time)
}
pub async fn get_block_by_time(network: &Network, client: &mut CompactTxStreamerClient<Channel>, time: u32) -> anyhow::Result<u32> {
let mut start = u32::from(network.activation_height(NetworkUpgrade::Sapling).unwrap());
let mut end = get_latest_height(client).await?;
if time <= get_block_date(client, start).await? { return Ok(0); }
if time >= get_block_date(client, end).await? { return Ok(end); }
let mut block_mid;
while end - start >= 1000 {
block_mid = (start + end) / 2;
let mid = get_block_date(client, block_mid).await?;
if time < mid {
end = block_mid - 1;
}
else if time > mid {
start = block_mid + 1;
}
else {
return Ok(block_mid);
}
}
Ok(start)
}
#[derive(Error, Debug)]
pub enum ChainError {
#[error("Blockchain reorganization")]

View File

@ -5,7 +5,7 @@ use crate::pay::TxBuilder;
use crate::prices::fetch_historical_prices;
use crate::scan::ProgressCallback;
use crate::taddr::{get_taddr_balance, get_utxos};
use crate::{broadcast_tx, connect_lightwalletd, get_latest_height, BlockId, CTree, DbAdapter, build_tx_ledger};
use crate::{broadcast_tx, connect_lightwalletd, get_latest_height, BlockId, CTree, DbAdapter, build_tx_ledger, CompactTxStreamerClient};
use bip39::{Language, Mnemonic};
use lazycell::AtomicLazyCell;
use rand::rngs::OsRng;
@ -23,6 +23,7 @@ use chacha20poly1305::aead::{Aead, NewAead};
use bech32::FromBase32;
use tokio::sync::Mutex;
use tonic::Request;
use tonic::transport::Channel;
use zcash_client_backend::address::RecipientAddress;
use zcash_client_backend::encoding::{
decode_extended_full_viewing_key, decode_extended_spending_key, encode_payment_address,
@ -35,6 +36,7 @@ use zcash_primitives::transaction::builder::Progress;
use zcash_primitives::transaction::components::Amount;
use zcash_proofs::prover::LocalTxProver;
use zcash_params::coin::{CoinChain, CoinType, get_coin_chain};
use crate::chain::{get_activation_date, get_block_by_time};
use crate::db::AccountBackup;
const DEFAULT_CHUNK_SIZE: u32 = 100_000;
@ -237,8 +239,13 @@ impl Wallet {
pub async fn skip_to_last_height(&self) -> anyhow::Result<()> {
let mut client = connect_lightwalletd(&self.ld_url).await?;
let last_height = get_latest_height(&mut client).await?;
self.store_tree_state(&mut client, last_height).await?;
Ok(())
}
async fn store_tree_state(&self, client: &mut CompactTxStreamerClient<Channel>, height: u32) -> anyhow::Result<()> {
let block_id = BlockId {
height: last_height as u64,
height: height as u64,
hash: vec![],
};
let block = client.get_block(block_id.clone()).await?.into_inner();
@ -248,13 +255,15 @@ impl Wallet {
.into_inner();
let tree = CTree::read(&*hex::decode(&tree_state.tree)?)?;
self.db
.store_block(last_height, &block.hash, block.time, &tree)?;
.store_block(height, &block.hash, block.time, &tree)?;
Ok(())
}
pub fn rewind_to_height(&mut self, height: u32) -> anyhow::Result<()> {
self.db.trim_to_height(height)
pub async fn rewind_to_height(&mut self, height: u32) -> anyhow::Result<()> {
let mut client = connect_lightwalletd(&self.ld_url).await?;
self.db.trim_to_height(height)?;
self.store_tree_state(&mut client, height).await?;
Ok(())
}
async fn prepare_multi_payment(
@ -591,6 +600,18 @@ impl Wallet {
Ok(tx_id)
}
pub async fn get_activation_date(&self) -> anyhow::Result<u32> {
let mut client = connect_lightwalletd(&self.ld_url).await?;
let date_time = get_activation_date(self.network(), &mut client).await?;
Ok(date_time)
}
pub async fn get_block_by_time(&self, time: u32) -> anyhow::Result<u32> {
let mut client = connect_lightwalletd(&self.ld_url).await?;
let date_time = get_block_by_time(self.network(), &mut client, time).await?;
Ok(date_time)
}
fn chain(&self) -> &dyn CoinChain { get_coin_chain(self.coin_type) }
fn network(&self) -> &Network { self.chain().network() }
}