Skip to content

Commit

Permalink
Merge pull request #31 from ChainSafe/willem/remove-sync2
Browse files Browse the repository at this point in the history
Remove the legacy sync algo
  • Loading branch information
ec2 authored Oct 1, 2024
2 parents ce39263 + 6a1dee7 commit f8d6049
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 189 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ native = ["tonic/channel", "tonic/gzip", "tonic/tls-webpki-roots", "tokio/macros
sqlite-db = ["dep:zcash_client_sqlite"]
console_error_panic_hook = ["dep:console_error_panic_hook"]
no-bundler = ["wasm-bindgen-rayon?/no-bundler", "wasm_thread/no-bundler"]
sync2 = []

[dependencies]
## Web dependencies
Expand Down
10 changes: 5 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ default:
just --list

build *features:
wasm-pack build --no-opt -t web --scope webzjs --release --out-dir ./packages/webz-core --no-default-features --features="wasm wasm-parallel sync2 {{features}}" -Z build-std="panic_abort,std"
wasm-pack build --no-opt -t web --scope webzjs --release --out-dir ./packages/webz-core --no-default-features --features="wasm wasm-parallel {{features}}" -Z build-std="panic_abort,std"

# All Wasm Tests
test-web *features:
WASM_BINDGEN_TEST_TIMEOUT=99999 wasm-pack test --release --firefox --no-default-features --features "wasm no-bundler {{features}}" -Z build-std="panic_abort,std"

# sync message board in the web: addigional args: sync2
# sync message board in the web: addigional args:
test-message-board-web *features:
WASM_BINDGEN_TEST_TIMEOUT=99999 wasm-pack test --release --chrome --no-default-features --features "wasm no-bundler {{features}}" -Z build-std="panic_abort,std" --test message-board-sync

# simple example in the web: additional args: sync2
# simple example in the web: additional args:
test-simple-web *features:
WASM_BINDGEN_TEST_TIMEOUT=99999 wasm-pack test --release --chrome --no-default-features --features "wasm no-bundler {{features}}" -Z build-std="panic_abort,std" --test simple-sync-and-send


# simple example: additional args: sync2, sqlite-db
# simple example: additional args:, sqlite-db
example-simple *features:
RUST_LOG="info,zcash_client_backend::sync=debug" cargo run -r --example simple-sync --features "native {{features}}"

# sync the message board: additional args: sync2, sqlite-db
# sync the message board: additional args:, sqlite-db
example-message-board *features:
RUST_LOG=info,zcash_client_backend::sync=debug cargo run -r --example message-board-sync --features "native {{features}}"

Expand Down
25 changes: 4 additions & 21 deletions src/bindgen/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use zcash_client_backend::proto::service::{
};
use zcash_client_memory::MemoryWalletDb;
use zcash_keys::keys::UnifiedFullViewingKey;
use zcash_primitives::consensus::{self, BlockHeight};
use zcash_primitives::consensus;
use zcash_primitives::transaction::TxId;

pub type MemoryWallet<T> = Wallet<MemoryWalletDb<consensus::Network>, T>;
Expand Down Expand Up @@ -126,31 +126,14 @@ impl WebWallet {
self.inner.suggest_scan_ranges().await
}

/// Synchronize the wallet with the blockchain up to the tip
/// The passed callback will be called for every batch of blocks processed with the current progress
pub async fn sync(&self, callback: &js_sys::Function) -> Result<(), Error> {
let callback = move |scanned_to: BlockHeight, tip: BlockHeight| {
let this = JsValue::null();
let _ = callback.call2(
&this,
&JsValue::from(Into::<u32>::into(scanned_to)),
&JsValue::from(Into::<u32>::into(tip)),
);
};

self.inner.sync(callback).await?;

Ok(())
}

/// Synchronize the wallet with the blockchain up to the tip using zcash_client_backend's algo
pub async fn sync2(&self) -> Result<(), Error> {
pub async fn sync(&self) -> Result<(), Error> {
assert!(!thread::is_web_worker_thread());

let db = self.inner.clone();

let sync_handler = thread::Builder::new()
.name("sync2".to_string())
.name("sync".to_string())
.spawn_async(|| async {
assert!(thread::is_web_worker_thread());
tracing::debug!(
Expand All @@ -159,7 +142,7 @@ impl WebWallet {
);

let db = db;
db.sync2().await.unwrap_throw();
db.sync().await.unwrap_throw();
})
.unwrap_throw()
.join_async();
Expand Down
137 changes: 4 additions & 133 deletions src/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::num::NonZeroU32;

use bip0039::{English, Mnemonic};
use futures_util::{StreamExt, TryStreamExt};
use nonempty::NonEmpty;
use secrecy::{ExposeSecret, SecretVec, Zeroize};
use tonic::{
Expand All @@ -22,23 +21,21 @@ use zcash_address::ZcashAddress;
use zcash_client_backend::data_api::wallet::{
create_proposed_transactions, input_selection::GreedyInputSelector, propose_transfer,
};
use zcash_client_backend::data_api::{scanning::ScanRange, WalletCommitmentTrees};
use zcash_client_backend::data_api::WalletCommitmentTrees;
use zcash_client_backend::data_api::{
Account, AccountBirthday, AccountPurpose, InputSource, NullifierQuery, WalletRead,
WalletSummary, WalletWrite,
Account, AccountBirthday, AccountPurpose, InputSource, WalletRead, WalletSummary, WalletWrite,
};
use zcash_client_backend::fees::zip317::SingleOutputChangeStrategy;
use zcash_client_backend::proposal::Proposal;
use zcash_client_backend::proto::service::{
self, compact_tx_streamer_client::CompactTxStreamerClient,
};
use zcash_client_backend::scanning::{scan_block, Nullifiers, ScanningKeys};
use zcash_client_backend::wallet::OvkPolicy;
use zcash_client_backend::zip321::{Payment, TransactionRequest};
use zcash_client_backend::ShieldedProtocol;
use zcash_client_memory::{MemBlockCache, MemoryWalletDb};
use zcash_keys::keys::{UnifiedFullViewingKey, UnifiedSpendingKey};
use zcash_primitives::consensus::{self, BlockHeight, Network};
use zcash_primitives::consensus::{self, Network};
use zcash_primitives::transaction::components::amount::NonNegativeAmount;
use zcash_primitives::transaction::fees::zip317::FeeRule;
use zcash_primitives::transaction::TxId;
Expand Down Expand Up @@ -227,7 +224,7 @@ where
})?)
}

pub async fn sync2(&self) -> Result<(), Error> {
pub async fn sync(&self) -> Result<(), Error> {
let mut client = self.client.clone();
// TODO: This should be held in the Wallet struct so we can download in parallel
let db_cache = MemBlockCache::new();
Expand All @@ -244,113 +241,6 @@ where
.map_err(Into::into)
}

/// Synchronize the wallet with the blockchain up to the tip
/// The passed callback will be called for every batch of blocks processed with the current progress
pub async fn sync(&self, callback: impl Fn(BlockHeight, BlockHeight)) -> Result<(), Error> {
let tip = self.update_chain_tip().await?;

tracing::info!("Retrieving suggested scan ranges from wallet");
let scan_ranges = self.db.read().await.suggest_scan_ranges()?;
tracing::info!("Suggested scan ranges: {:?}", scan_ranges);

// TODO: Ensure wallet's view of the chain tip as of the previous wallet session is valid.
// See https://github.com/Electric-Coin-Company/zec-sqlite-cli/blob/8c2e49f6d3067ec6cc85248488915278c3cb1c5a/src/commands/sync.rs#L157

// Download and process all blocks in the requested ranges
// Split each range into BATCH_SIZE chunks to avoid requesting too many blocks at once
for scan_range in scan_ranges.into_iter().flat_map(|r| {
// Limit the number of blocks we download and scan at any one time.
(0..).scan(r, |acc, _| {
if acc.is_empty() {
None
} else if let Some((cur, next)) = acc.split_at(acc.block_range().start + BATCH_SIZE)
{
*acc = next;
Some(cur)
} else {
let cur = acc.clone();
let end = acc.block_range().end;
*acc = ScanRange::from_parts(end..end, acc.priority());
Some(cur)
}
})
}) {
self.fetch_and_scan_range(
scan_range.block_range().start.into(),
scan_range.block_range().end.into(),
)
.await?;
callback(scan_range.block_range().end, tip);
}

Ok(())
}

/// Download and process all blocks in the given range
async fn fetch_and_scan_range(&self, start: u32, end: u32) -> Result<(), Error> {
let mut client = self.client.clone();
// get the chainstate prior to the range
let tree_state = client
.get_tree_state(service::BlockId {
height: (start - 1).into(),
..Default::default()
})
.await?;
let chainstate = tree_state.into_inner().to_chain_state()?;

// Get the scanning keys from the DB
let account_ufvks = self.db.read().await.get_unified_full_viewing_keys()?;
let scanning_keys = ScanningKeys::from_account_ufvks(account_ufvks);

// Get the nullifiers for the unspent notes we are tracking
let nullifiers = Nullifiers::new(
self.db
.read()
.await
.get_sapling_nullifiers(NullifierQuery::Unspent)?,
self.db
.read()
.await
.get_orchard_nullifiers(NullifierQuery::Unspent)?,
);

let range = service::BlockRange {
start: Some(service::BlockId {
height: start.into(),
..Default::default()
}),
end: Some(service::BlockId {
height: (end - 1).into(),
..Default::default()
}),
};

tracing::info!("Scanning block range: {:?} to {:?}", start, end);

let scanned_blocks = client
.get_block_range(range)
.await?
.into_inner()
.map(|compact_block| {
scan_block(
&self.network,
compact_block.unwrap(),
&scanning_keys,
&nullifiers,
None,
)
})
.try_collect()
.await?;

self.db
.write()
.await
.put_blocks(&chainstate, scanned_blocks)?;

Ok(())
}

pub async fn get_wallet_summary(&self) -> Result<Option<WalletSummary<AccountId>>, Error> {
Ok(self
.db
Expand All @@ -359,25 +249,6 @@ where
.get_wallet_summary(self.min_confirmations.into())?)
}

pub(crate) async fn update_chain_tip(&self) -> Result<BlockHeight, Error> {
tracing::info!("Retrieving chain tip from lightwalletd");

let tip_height = self
.client
.clone()
.get_latest_block(service::ChainSpec::default())
.await?
.get_ref()
.height
.try_into()
.unwrap();

tracing::info!("Latest block height is {}", tip_height);
self.db.write().await.update_chain_tip(tip_height)?;

Ok(tip_height)
}

///
/// Create a transaction proposal to send funds from the wallet to a given address
///
Expand Down
18 changes: 3 additions & 15 deletions tests/message-board-sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,9 @@ async fn test_message_board() {
let id = w.import_ufvk(&ufvk_str, Some(2477329)).await.unwrap();
tracing::info!("Created account with id: {}", id);

#[cfg(not(feature = "sync2"))]
{
tracing::info!("Syncing wallet with our sync impl");
w.sync(&js_sys::Function::new_with_args(
"scanned_to, tip",
"console.log('Scanned: ', scanned_to, '/', tip)",
))
.await
.unwrap();
}
#[cfg(feature = "sync2")]
{
tracing::info!("Syncing wallet with sync2");
w.sync2().await.unwrap();
}
tracing::info!("Syncing wallet with our sync impl");
w.sync().await.unwrap();

tracing::info!("Syncing complete :)");

let summary = w.get_wallet_summary().await.unwrap();
Expand Down
16 changes: 2 additions & 14 deletions tests/simple-sync-and-send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,8 @@ async fn test_get_and_scan_range() {
let w_clone = w.clone();
let w = w_clone;

#[cfg(not(feature = "sync2"))]
{
w.sync(&js_sys::Function::new_with_args(
"scanned_to, tip",
"console.log('Scanned: ', scanned_to, '/', tip)",
))
.await
.unwrap();
}
#[cfg(feature = "sync2")]
{
tracing::info!("Syncing wallet with sync2");
w.sync2().await.unwrap();
}
w.sync().await.unwrap();

tracing::info!("Syncing complete :)");

let summary = w.get_wallet_summary().await.unwrap();
Expand Down

0 comments on commit f8d6049

Please sign in to comment.