From bb388436c727aac19934dba8edf373d8f22f74b2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 31 Jan 2025 04:58:43 +0000 Subject: [PATCH] Call `init_wallet_db` in `Wallet::open` This ensures that the database file exists and has the latest migrations applied. Limitation: it does not yet handle migrations that require access to a seed, which means it won't work with existing old `zcash_client_sqlite` databases (migrate these with `zcash-devtool wallet upgrade` first). --- Cargo.lock | 23 ++++++------ Cargo.toml | 11 +++--- zallet/Cargo.toml | 1 + zallet/src/commands/start.rs | 3 +- zallet/src/components/wallet.rs | 43 ++++++++++++++++++---- zallet/src/components/wallet/connection.rs | 2 +- 6 files changed, 58 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f4cc71..05d39b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -774,7 +774,7 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "blake2b_simd", "core2", @@ -809,7 +809,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "blake2b_simd", ] @@ -3554,6 +3554,7 @@ dependencies = [ "rusqlite", "rust-embed", "sapling-crypto", + "schemerz", "secrecy 0.8.0", "serde", "serde_json", @@ -3573,7 +3574,7 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.6.2" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "bech32", "bs58", @@ -3586,7 +3587,7 @@ dependencies = [ [[package]] name = "zcash_client_backend" version = "0.16.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "async-trait", "base64", @@ -3634,7 +3635,7 @@ dependencies = [ [[package]] name = "zcash_client_sqlite" version = "0.14.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "bip32", "bs58", @@ -3672,7 +3673,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.2" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "core2", "nonempty", @@ -3681,7 +3682,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.6.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "bech32", "bip32", @@ -3722,7 +3723,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.21.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "bip32", "blake2b_simd", @@ -3761,7 +3762,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.4.3" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "core2", "document-features", @@ -3781,7 +3782,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.1.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "bip32", "blake2b_simd", @@ -3857,7 +3858,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=b106a89841c493c37bc269b6b5c490727f10ed91#b106a89841c493c37bc269b6b5c490727f10ed91" +source = "git+https://github.com/zcash/librustzcash.git?rev=895b298a2b042ae352a8a9f0fd4176c3db78253e#895b298a2b042ae352a8a9f0fd4176c3db78253e" dependencies = [ "base64", "nom", diff --git a/Cargo.toml b/Cargo.toml index c0dd44f..080d3de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,6 +63,7 @@ deadpool = "0.12" deadpool-sqlite = "0.9" deadpool-sync = "0.1" rusqlite = "0.32" +schemerz = "0.2" secrecy = "0.8" shardtree = "0.5" zcash_client_backend = "0.16" @@ -76,8 +77,8 @@ tonic = "0.12" orchard = { git = "https://github.com/zcash/orchard.git", rev = "c684e9185a0449efb00428f807d3bf286b5dae03" } redjubjub = { git = "https://github.com/ZcashFoundation/redjubjub", rev = "eae848c5c14d9c795d000dd9f4c4762d1aee7ee1" } sapling = { package = "sapling-crypto", git = "https://github.com/zcash/sapling-crypto.git", rev = "e607c52d13bb7ade66293f9ab8d07e311f4ad868" } -transparent = { package = "zcash_transparent", git = "https://github.com/zcash/librustzcash.git", rev = "b106a89841c493c37bc269b6b5c490727f10ed91" } -zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "b106a89841c493c37bc269b6b5c490727f10ed91" } -zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "b106a89841c493c37bc269b6b5c490727f10ed91" } -zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "b106a89841c493c37bc269b6b5c490727f10ed91" } -zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "b106a89841c493c37bc269b6b5c490727f10ed91" } +transparent = { package = "zcash_transparent", git = "https://github.com/zcash/librustzcash.git", rev = "895b298a2b042ae352a8a9f0fd4176c3db78253e" } +zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "895b298a2b042ae352a8a9f0fd4176c3db78253e" } +zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "895b298a2b042ae352a8a9f0fd4176c3db78253e" } +zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "895b298a2b042ae352a8a9f0fd4176c3db78253e" } +zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "895b298a2b042ae352a8a9f0fd4176c3db78253e" } diff --git a/zallet/Cargo.toml b/zallet/Cargo.toml index 5b82aa8..f1977ce 100644 --- a/zallet/Cargo.toml +++ b/zallet/Cargo.toml @@ -29,6 +29,7 @@ rand.workspace = true rusqlite.workspace = true rust-embed.workspace = true sapling.workspace = true +schemerz.workspace = true secrecy.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/zallet/src/commands/start.rs b/zallet/src/commands/start.rs index 8b3ba32..8a2333e 100644 --- a/zallet/src/commands/start.rs +++ b/zallet/src/commands/start.rs @@ -27,7 +27,8 @@ impl StartCmd { .into()); } - Wallet::open(path, config.network(), self.lwd_server.clone())? + info!("Opening wallet"); + Wallet::open(path, config.network(), self.lwd_server.clone()).await? }; // Launch RPC server. diff --git a/zallet/src/components/wallet.rs b/zallet/src/components/wallet.rs index 226846c..429ceb9 100644 --- a/zallet/src/components/wallet.rs +++ b/zallet/src/components/wallet.rs @@ -2,10 +2,11 @@ use std::fmt; use std::path::Path; use std::time::Duration; -use abscissa_core::{Component, FrameworkError}; +use abscissa_core::{tracing::info, Component, FrameworkError}; use abscissa_tokio::TokioComponent; -use tokio::{task::JoinHandle, time}; +use tokio::{fs, task::JoinHandle, time}; use zcash_client_backend::sync; +use zcash_client_sqlite::wallet::init::{init_wallet_db, WalletMigrationError}; use crate::{ error::{Error, ErrorKind}, @@ -38,17 +39,45 @@ impl fmt::Debug for Wallet { } impl Wallet { - pub fn open( + pub async fn open( path: impl AsRef, params: Network, lightwalletd_server: Servers, ) -> Result { - let db_data_pool = connection::pool(path, params)?; - Ok(Self { + let wallet_exists = fs::try_exists(&path) + .await + .map_err(|e| ErrorKind::Init.context(e))?; + + let wallet = Self { params, - db_data_pool, + db_data_pool: connection::pool(path, params)?, lightwalletd_server, - }) + }; + + if wallet_exists { + info!("Applying latest database migrations"); + } else { + info!("Creating empty database"); + } + let handle = wallet.handle().await?; + handle.with_mut(|mut db_data| { + match init_wallet_db(&mut db_data, None) { + Ok(()) => Ok(()), + // TODO: Support single-seed migrations once we have key storage. + // https://github.com/zcash/wallet/issues/18 + // TODO: Support multi-seed or seed-absent migrations. + // https://github.com/zcash/librustzcash/issues/1284 + Err(schemerz::MigratorError::Migration { + error: WalletMigrationError::SeedRequired, + .. + }) => Err(ErrorKind::Init.context("TODO: Support seed-required migrations")), + Err(e) => Err(ErrorKind::Init.context(e)), + }?; + + Ok::<(), Error>(()) + })?; + + Ok(wallet) } /// Called automatically after `TokioComponent` is initialized diff --git a/zallet/src/components/wallet/connection.rs b/zallet/src/components/wallet/connection.rs index c6817fa..e365509 100644 --- a/zallet/src/components/wallet/connection.rs +++ b/zallet/src/components/wallet/connection.rs @@ -98,7 +98,7 @@ impl WalletConnection { }) } - fn with_mut(&self, f: impl FnOnce(WalletDb<&mut rusqlite::Connection, Network>) -> T) -> T { + pub(crate) fn with_mut(&self, f: impl FnOnce(WalletDb<&mut rusqlite::Connection, Network>) -> T) -> T { tokio::task::block_in_place(|| { f(WalletDb::from_connection( self.inner.lock().unwrap().as_mut(),