Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this library adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Added the Rust `zcash_voting` dependency foundation for future shielded voting backend work.

### Changed
- `Synchronizer.importAccountByUfvk` now calls `TypesafeBackend.rewindToChainState` after importing
an account. This enables imported accounts to discover their history and funds, at the cost of
Expand Down
52 changes: 52 additions & 0 deletions backend-lib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion backend-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ rust-version = "1.92"

[dependencies]
# Zcash dependencies
orchard = "0.13"
orchard = { version = "=0.13.1", features = ["unstable-voting-circuits"] }
pczt = { version = "0.6", features = ["prover", "orchard", "sapling"] }
sapling = { package = "sapling-crypto", version = "0.7", default-features = false }
transparent = { package = "zcash_transparent", version = "0.7", default-features = false }
Expand Down Expand Up @@ -77,6 +77,9 @@ xz2 = { version = "0.1", features = ["static"] }
component = "0.1.1"
rust-analyzer = "0.0.1"

# Shielded voting
zcash_voting = { version = "0.5.3", default-features = false }

## Uncomment this to test librustzcash changes locally
#[patch.crates-io]
#pczt = { package = "pczt", path = '../../clones/librustzcash/pczt' }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cash.z.ecc.android.sdk.internal.jni

internal object VotingRustBackend {
suspend fun new(): VotingRustBackend {
RustBackend.loadLibrary()
return this
}

@JvmStatic
external fun computeShareNullifier(
voteCommitment: ByteArray,
primaryBlind: ByteArray,
shareIndex: Int
): ByteArray?
}
1 change: 1 addition & 0 deletions backend-lib/src/main/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ use crate::utils::{
mod eip681;
mod tor;
mod utils;
mod voting;

#[cfg(debug_assertions)]
fn print_debug_state() {
Expand Down
45 changes: 45 additions & 0 deletions backend-lib/src/main/rust/voting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! JNI bindings for the zcash_voting crate.

use std::ptr;

use anyhow::anyhow;
use jni::{
JNIEnv,
objects::{JByteArray, JClass},
sys::{jbyteArray, jint},
};
use zcash_voting as voting;

use crate::utils::{self, catch_unwind, exception::unwrap_exc_or};

/// Compute the share reveal nullifier from client-known inputs.
///
/// Returns the 32-byte nullifier, or throws a RuntimeException and returns null
/// on malformed inputs.
#[unsafe(no_mangle)]
pub extern "C" fn Java_cash_z_ecc_android_sdk_internal_jni_VotingRustBackend_computeShareNullifier<
'local,
>(
mut env: JNIEnv<'local>,
_: JClass<'local>,
vote_commitment: JByteArray<'local>,
primary_blind: JByteArray<'local>,
share_index: jint,
) -> jbyteArray {
let res = catch_unwind(&mut env, |env| {
let share_index =
u32::try_from(share_index).map_err(|_| anyhow!("shareIndex must be non-negative"))?;
let vote_commitment = utils::java_bytes_to_rust(env, &vote_commitment)?;
let primary_blind = utils::java_bytes_to_rust(env, &primary_blind)?;

let nullifier = voting::share_tracking::compute_share_nullifier(
&vote_commitment,
share_index,
&primary_blind,
)
.map_err(|e| anyhow!("compute_share_nullifier failed: {}", e))?;

Ok(utils::rust_bytes_to_java(env, &nullifier)?.into_raw())
});
unwrap_exc_or(&mut env, res, ptr::null_mut())
}