From c4b5c70b7dc255fa4d508ecb6e73a598d36e8d6d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 12 Nov 2022 15:29:02 +1300 Subject: [PATCH] Migrate to published Zcash Rust crates with ZIP 317 support ZIP 317 fee calculations are hard-coded off, continuing to use the fixed fee logic for now, but enabling them in a future SDK update is now possible. --- sdk-lib/Cargo.lock | 59 ++++---- sdk-lib/Cargo.toml | 18 +-- .../cash/z/ecc/android/sdk/jni/RustBackend.kt | 12 +- sdk-lib/src/main/rust/lib.rs | 138 ++++++++++++++---- 4 files changed, 152 insertions(+), 75 deletions(-) diff --git a/sdk-lib/Cargo.lock b/sdk-lib/Cargo.lock index 072da59e..bd1c9225 100644 --- a/sdk-lib/Cargo.lock +++ b/sdk-lib/Cargo.lock @@ -566,7 +566,8 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" dependencies = [ "blake2b_simd", "byteorder", @@ -575,7 +576,8 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75" dependencies = [ "blake2b_simd", ] @@ -1121,7 +1123,7 @@ dependencies = [ "serde", "subtle", "tracing", - "zcash_note_encryption 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption", ] [[package]] @@ -1494,6 +1496,7 @@ dependencies = [ "fallible-iterator", "fallible-streaming-iterator", "hashlink", + "lazy_static", "libsqlite3-sys", "memchr", "smallvec", @@ -1533,7 +1536,8 @@ dependencies = [ [[package]] name = "schemer" version = "0.2.0" -source = "git+https://github.com/aschampion/schemer.git?rev=6726b60f43f72c6e24a18d31be0ec7d42829e5e1#6726b60f43f72c6e24a18d31be0ec7d42829e5e1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f0ed79b582101b59740acd981e58eaa3bf8c4b1179e9a0124a7df1e08e98b3" dependencies = [ "daggy", "log", @@ -1543,8 +1547,9 @@ dependencies = [ [[package]] name = "schemer-rusqlite" -version = "0.2.0" -source = "git+https://github.com/aschampion/schemer.git?rev=6726b60f43f72c6e24a18d31be0ec7d42829e5e1#6726b60f43f72c6e24a18d31be0ec7d42829e5e1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1f34ab2dd976536b8518fe5b868756cf6e6caec89f38d8b6f432ba27f1d5f27" dependencies = [ "rusqlite", "schemer", @@ -2131,7 +2136,8 @@ dependencies = [ [[package]] name = "zcash_address" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804268e702b664fc09d3e2ce82786d0addf4ae57ba6976469be63e09066bf9f7" dependencies = [ "bech32", "bs58", @@ -2141,8 +2147,9 @@ dependencies = [ [[package]] name = "zcash_client_backend" -version = "0.5.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee7748e874300bf574bdb524108b8967d3e58685aa1705dd2efbcfabb21b89d7" dependencies = [ "base64", "bech32", @@ -2166,14 +2173,15 @@ dependencies = [ "which", "zcash_address", "zcash_encoding", - "zcash_note_encryption 0.2.0 (git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4)", + "zcash_note_encryption", "zcash_primitives", ] [[package]] name = "zcash_client_sqlite" -version = "0.3.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9625b097932fc26f4b549042eafff922b57bcd421edba408abf6334a97298636" dependencies = [ "bs58", "group", @@ -2193,7 +2201,8 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03391b81727875efa6ac0661a20883022b6fba92365dc121c48fa9b00c5aac0" dependencies = [ "byteorder", "nonempty", @@ -2212,22 +2221,11 @@ dependencies = [ "subtle", ] -[[package]] -name = "zcash_note_encryption" -version = "0.2.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" -dependencies = [ - "chacha20", - "chacha20poly1305", - "cipher 0.4.3", - "rand_core", - "subtle", -] - [[package]] name = "zcash_primitives" -version = "0.8.1" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e33ec9068388e8de106a78268f90487d6975b171ee197aef16cc64c093486d" dependencies = [ "aes", "bip0039", @@ -2256,13 +2254,14 @@ dependencies = [ "subtle", "zcash_address", "zcash_encoding", - "zcash_note_encryption 0.2.0 (git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4)", + "zcash_note_encryption", ] [[package]] name = "zcash_proofs" -version = "0.8.0" -source = "git+https://github.com/zcash/librustzcash.git?rev=6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4#6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77381adc72286874e563ee36ba99953946abcbd195ada45440a2754ca823d407" dependencies = [ "bellman", "blake2b_simd", diff --git a/sdk-lib/Cargo.toml b/sdk-lib/Cargo.toml index 5230a5c2..53c5ebb1 100644 --- a/sdk-lib/Cargo.toml +++ b/sdk-lib/Cargo.toml @@ -23,20 +23,10 @@ schemer = "0.2" secp256k1 = "0.21" secrecy = "0.8" zcash_address = "0.2" -zcash_client_backend = { version = "0.5", features = ["transparent-inputs", "unstable"] } -zcash_client_sqlite = { version = "0.3", features = ["transparent-inputs", "unstable"] } -zcash_primitives = "0.8" -zcash_proofs = "0.8" - -# Revision corresponds to the pending zcash_primitives 0.8.0. -[patch.crates-io] -schemer = { git = "https://github.com/aschampion/schemer.git", rev = "6726b60f43f72c6e24a18d31be0ec7d42829e5e1" } -schemer-rusqlite = { git = "https://github.com/aschampion/schemer.git", rev = "6726b60f43f72c6e24a18d31be0ec7d42829e5e1" } -zcash_address = { git = 'https://github.com/zcash/librustzcash.git', rev='6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4' } -zcash_client_backend = { git = 'https://github.com/zcash/librustzcash.git', rev='6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4' } -zcash_client_sqlite = { git = 'https://github.com/zcash/librustzcash.git', rev='6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4' } -zcash_primitives = { git = 'https://github.com/zcash/librustzcash.git', rev='6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4' } -zcash_proofs = { git = 'https://github.com/zcash/librustzcash.git', rev='6f4a6aa00cc2db7864d01c7403cbcd75dd45bda4' } +zcash_client_backend = { version = "0.6", features = ["transparent-inputs", "unstable"] } +zcash_client_sqlite = { version = "0.4", features = ["transparent-inputs", "unstable"] } +zcash_primitives = "0.9" +zcash_proofs = "0.9" ## Uncomment this to test librustzcash changes locally #[patch.crates-io] diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt index 845f2873..4fa3c420 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/jni/RustBackend.kt @@ -227,7 +227,8 @@ internal class RustBackend private constructor( memo ?: ByteArray(0), File(saplingParamDir, SaplingParamTool.SPEND_PARAM_FILE_NAME).absolutePath, File(saplingParamDir, SaplingParamTool.OUTPUT_PARAM_FILE_NAME).absolutePath, - networkId = network.id + networkId = network.id, + useZip317Fees = false ) } @@ -243,7 +244,8 @@ internal class RustBackend private constructor( memo ?: ByteArray(0), File(saplingParamDir, SaplingParamTool.SPEND_PARAM_FILE_NAME).absolutePath, File(saplingParamDir, SaplingParamTool.OUTPUT_PARAM_FILE_NAME).absolutePath, - networkId = network.id + networkId = network.id, + useZip317Fees = false ) } } @@ -486,7 +488,8 @@ internal class RustBackend private constructor( memo: ByteArray, spendParamsPath: String, outputParamsPath: String, - networkId: Int + networkId: Int, + useZip317Fees: Boolean ): Long @JvmStatic @@ -497,7 +500,8 @@ internal class RustBackend private constructor( memo: ByteArray, spendParamsPath: String, outputParamsPath: String, - networkId: Int + networkId: Int, + useZip317Fees: Boolean ): Long @JvmStatic diff --git a/sdk-lib/src/main/rust/lib.rs b/sdk-lib/src/main/rust/lib.rs index 33130c8b..a6421c00 100644 --- a/sdk-lib/src/main/rust/lib.rs +++ b/sdk-lib/src/main/rust/lib.rs @@ -23,21 +23,22 @@ use zcash_client_backend::keys::{DecodingError, UnifiedSpendingKey}; use zcash_client_backend::{ address::{RecipientAddress, UnifiedAddress}, data_api::{ - chain::{scan_cached_blocks, validate_chain}, - error::Error, + chain::{self, scan_cached_blocks, validate_chain}, wallet::{ - create_spend_to_address, decrypt_and_store_transaction, shield_transparent_funds, + decrypt_and_store_transaction, input_selection::GreedyInputSelector, + shield_transparent_funds, spend, }, WalletRead, WalletWrite, }, encoding::AddressCodec, + fees::DustOutputPolicy, keys::{Era, UnifiedFullViewingKey}, wallet::{OvkPolicy, WalletTransparentOutput}, + zip321::{Payment, TransactionRequest}, }; #[allow(deprecated)] use zcash_client_sqlite::wallet::get_rewind_height; use zcash_client_sqlite::{ - error::SqliteClientError, wallet::init::{init_accounts_table, init_blocks_table, init_wallet_db, WalletMigrationError}, BlockDb, NoteId, WalletDb, }; @@ -59,6 +60,16 @@ use crate::utils::exception::unwrap_exc_or; mod utils; +// Combine imports into common namespaces. +mod fixed { + pub(super) use zcash_client_backend::fees::fixed::*; + pub(super) use zcash_primitives::transaction::fees::fixed::*; +} +mod zip317 { + pub(super) use zcash_client_backend::fees::zip317::*; + pub(super) use zcash_primitives::transaction::fees::zip317::*; +} + const ANCHOR_OFFSET: u32 = 10; #[cfg(debug_assertions)] @@ -705,7 +716,7 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_getVerified }) .and_then(|anchor| { (&db_data) - .get_unspent_transparent_outputs(&taddr, anchor - ANCHOR_OFFSET) + .get_unspent_transparent_outputs(&taddr, anchor - ANCHOR_OFFSET, &[]) .map_err(|e| format_err!("Error while fetching verified balance: {}", e)) })? .iter() @@ -743,7 +754,7 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_getTotalTra }) .and_then(|anchor| { (&db_data) - .get_unspent_transparent_outputs(&taddr, anchor) + .get_unspent_transparent_outputs(&taddr, anchor, &[]) .map_err(|e| format_err!("Error while fetching verified balance: {}", e)) })? .iter() @@ -865,8 +876,8 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_validateCom if let Err(e) = val_res { match e { - SqliteClientError::BackendError(Error::InvalidChain(upper_bound, _)) => { - let upper_bound_u32 = u32::from(upper_bound); + chain::error::Error::Chain(e) => { + let upper_bound_u32 = u32::from(e.at_height()); Ok(upper_bound_u32 as i64) } _ => Err(format_err!("Error while validating chain: {}", e)), @@ -1044,6 +1055,29 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_decryptAndS unwrap_exc_or(&env, res, JNI_FALSE) } +fn zip317_helper( + context: Ctx, + use_zip317_fees: jboolean, + enabled: impl FnOnce(Ctx, GreedyInputSelector) -> R, + disabled: impl FnOnce(Ctx, GreedyInputSelector) -> R, +) -> R { + if use_zip317_fees == JNI_TRUE { + let input_selector = GreedyInputSelector::new( + zip317::SingleOutputChangeStrategy::new(zip317::FeeRule::standard()), + DustOutputPolicy::default(), + ); + + enabled(context, input_selector) + } else { + let input_selector = GreedyInputSelector::new( + fixed::SingleOutputChangeStrategy::new(fixed::FeeRule::standard()), + DustOutputPolicy::default(), + ); + + disabled(context, input_selector) + } +} + #[no_mangle] pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_createToAddress( env: JNIEnv<'_>, @@ -1056,6 +1090,7 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_createToAdd spend_params: JString<'_>, output_params: JString<'_>, network_id: jint, + use_zip317_fees: jboolean, ) -> jlong { let res = panic::catch_unwind(|| { let network = parse_network(network_id as u32)?; @@ -1091,18 +1126,46 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_createToAdd let prover = LocalTxProver::new(Path::new(&spend_params), Path::new(&output_params)); - create_spend_to_address( - &mut db_data, - &network, - prover, - &usk, - &to, - value, + let request = TransactionRequest::new(vec![Payment { + recipient_address: to, + amount: value, memo, - OvkPolicy::Sender, - ANCHOR_OFFSET, + label: None, + message: None, + other_params: vec![], + }]) + .map_err(|e| format_err!("Error creating transaction request: {:?}", e))?; + + zip317_helper( + (&mut db_data, prover, request), + use_zip317_fees, + |(wallet_db, prover, request), input_selector| { + spend( + wallet_db, + &network, + prover, + &input_selector, + &usk, + request, + OvkPolicy::Sender, + ANCHOR_OFFSET, + ) + .map_err(|e| format_err!("Error while creating transaction: {}", e)) + }, + |(wallet_db, prover, request), input_selector| { + spend( + wallet_db, + &network, + prover, + &input_selector, + &usk, + request, + OvkPolicy::Sender, + ANCHOR_OFFSET, + ) + .map_err(|e| format_err!("Error while creating transaction: {}", e)) + }, ) - .map_err(|e| format_err!("Error while creating transaction: {}", e)) }); unwrap_exc_or(&env, res, -1) } @@ -1117,6 +1180,7 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_shieldToAdd spend_params: JString<'_>, output_params: JString<'_>, network_id: jint, + use_zip317_fees: jboolean, ) -> jlong { let res = panic::catch_unwind(|| { let network = parse_network(network_id as u32)?; @@ -1159,16 +1223,36 @@ pub unsafe extern "C" fn Java_cash_z_ecc_android_sdk_jni_RustBackend_shieldToAdd let prover = LocalTxProver::new(Path::new(&spend_params), Path::new(&output_params)); - shield_transparent_funds( - &mut db_data, - &network, - prover, - &usk, - &from_addrs, - &MemoBytes::from(&memo), - min_confirmations, + zip317_helper( + (&mut db_data, prover), + use_zip317_fees, + |(wallet_db, prover), input_selector| { + shield_transparent_funds( + wallet_db, + &network, + prover, + &input_selector, + &usk, + &from_addrs, + &MemoBytes::from(&memo), + min_confirmations, + ) + .map_err(|e| format_err!("Error while shielding transaction: {}", e)) + }, + |(wallet_db, prover), input_selector| { + shield_transparent_funds( + wallet_db, + &network, + prover, + &input_selector, + &usk, + &from_addrs, + &MemoBytes::from(&memo), + min_confirmations, + ) + .map_err(|e| format_err!("Error while shielding transaction: {}", e)) + }, ) - .map_err(|e| format_err!("Error while shielding transaction: {}", e)) }); unwrap_exc_or(&env, res, -1) }