Skip to content

[#2193] Add Android voting JNI round lifecycle#1938

Merged
nullcopy merged 13 commits into
mainfrom
greg/voting-jni-db-rounds
May 12, 2026
Merged

[#2193] Add Android voting JNI round lifecycle#1938
nullcopy merged 13 commits into
mainfrom
greg/voting-jni-db-rounds

Conversation

@greg0x

@greg0x greg0x commented May 8, 2026

Copy link
Copy Markdown
Collaborator

Part of zodl-inc/zodl-android#2193.
Slice of #1924 (umbrella draft PR being split into reviewable pieces).
Depends on #1934 (first slice — zcash_voting dependency foundation).
Resolves MOB-1109

Why

Second slice of the Android shielded-voting integration. #1934 wires the zcash_voting crate into backend-lib; this PR adds the voting DB handle and round lifecycle so the round-keyed surface (init / state / list / get-votes / clear / delete-skipped) compiles end-to-end from Rust through JNI to Kotlin.

Foundation for the Coinholder Polling flow tracked in zodl-inc/zodl-android#2193 — no user-visible behavior on its own.

What's in

Rust / JNI (backend-lib/src/main/rust/voting/):

  • db.rs — open/close native handle, setWalletId
  • rounds.rsinitRound, getRoundState, listRoundsJson, getVotesJson, clearRound, deleteSkippedBundles
  • share_tracking.rs — existing computeShareNullifier, lifted out of the monolithic module
  • helpers.rs — shared JNI helpers: fixed-width byte validation (PROTOCOL_FIELD_BYTES = 32), jint/jlong widening, RoundStateFfiRoundState construction
  • json.rs — round summary / vote record serialization, RoundPhaseu32 mapping
  • voting.rs — reduced to module roots + shared imports

Kotlin (sdk-lib/.../internal/):

  • jni/VotingRustBackend.kt — external declarations for the new surface
  • TypesafeVotingBackend.kt + impl — suspend wrappers, IO dispatcher, error checks, JSON → VoteRecord parsing
  • model/voting/FfiVotingModels.ktFfiRoundState, FfiRoundPhase

Not included

  • hotkey generation
  • bundle setup/count
  • proving cache warmup
  • delegation proving/submission
  • vote commitment or share payloads
  • recovery/share tracking
  • public Synchronizer voting API

Review focus

Primary review track: core-dev. Please look at:

  • native handle lifecycle (Box::into_raw / Box::from_raw across openVotingDb/closeVotingDb, Arc<VotingDb> usage)
  • JNI boundary error semantics (panic-safe via catch_unwind, exception conversion)
  • byte-array validation (java_bytes_exact on 32-byte protocol fields)
  • RoundState / RoundSummary JSON and FFI mapping
  • Kotlin surface is intentionally internal and minimal — just enough to compile and exercise the JNI

Swift counterparts:

Validation

  • cargo check --manifest-path backend-lib/Cargo.toml --locked
  • cargo fmt --manifest-path backend-lib/Cargo.toml --check
  • ./gradlew :backend-lib:compileReleaseKotlin :sdk-lib:compileReleaseKotlin
  • ./gradlew ktlint detektAll
  • ./gradlew checkProperties
  • git diff --check

Author

  • Self-review your own code in GitHub web interface
  • Add automated tests as appropriate
  • Update the manual tests as appropriate
  • Check the code coverage report for the automated tests
  • Update documentation as appropriate
  • Run the demo app and try the changes
  • Pull in the latest changes from the main branch and squash your commits before assigning a reviewer

Reviewer

  • Check the code with the Code Review Guidelines checklist
  • Perform an ad hoc review
  • Review the automated tests
  • Review the manual tests
  • Review the documentation as appropriate
  • Run the demo app and try the changes

p0mvn
p0mvn previously approved these changes May 8, 2026
@greg0x greg0x force-pushed the greg/voting-rust-foundation branch from 75a95d7 to 350e2b1 Compare May 10, 2026 23:29
@greg0x greg0x force-pushed the greg/voting-jni-db-rounds branch from 7171d4a to f0106ae Compare May 10, 2026 23:29

@noop-sk noop-sk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR added into code

Base automatically changed from greg/voting-rust-foundation to main May 11, 2026 09:33
@greg0x greg0x dismissed p0mvn’s stale review May 11, 2026 09:33

The base branch was changed.

Comment thread backend-lib/src/main/rust/voting/helpers.rs
Comment thread backend-lib/src/main/rust/voting/rounds.rs Outdated
Comment thread backend-lib/src/main/rust/voting/json.rs Outdated
VOTE_READY(FFI_ROUND_PHASE_VOTE_READY);

companion object {
fun fromInt(value: Int) =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forward compatibility risk

This throws if Rust adds a new RoundPhase variant before Kotlin is updated — a library update alone can crash the app. For an internal sdk-lib boundary it is defensible, but consider an UNKNOWN(-1) fallback or returning null until the phase set is stable.

@greg0x greg0x May 11, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an internal api contract between rust and kotlin. For this it's better to fail as soon as possible so the issue comes out during dev, failing silently.

The phase set can also be considered stable.

p.s.: I wish we could enjoy the comfort of UniFFI which solves this problem at generation time.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p.s.: I wish we could enjoy the comfort of UniFFI which solves this problem at generation time.

@noop-sk Is this something we should track as a future improvement?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

Comment thread sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeVotingBackend.kt Outdated
Comment thread backend-lib/src/main/rust/voting/db.rs

fn next_handle() -> anyhow::Result<jlong> {
NEXT_DB_HANDLE
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |id| {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nuttycomOrdering::Relaxed on both the success and failure orderings of fetch_update is correct for a monotone uniqueness counter on its own, since the registry Mutex provides the necessary acquire/release barriers around the actual map insert. Just flagging for a second pair of eyes given the subtle interaction between the two synchronization primitives.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirm, that the above is correct.

Comment thread backend-lib/src/main/rust/voting/rounds.rs

@nullcopy nullcopy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 3c8bd28

Comment thread backend-lib/src/main/rust/voting/helpers.rs Outdated
VOTE_READY(FFI_ROUND_PHASE_VOTE_READY);

companion object {
fun fromInt(value: Int) =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p.s.: I wish we could enjoy the comfort of UniFFI which solves this problem at generation time.

@noop-sk Is this something we should track as a future improvement?

@greg0x greg0x force-pushed the greg/voting-jni-db-rounds branch from 30a2201 to 450fe29 Compare May 11, 2026 23:31
@greg0x greg0x requested a review from nullcopy May 11, 2026 23:35

@nullcopy nullcopy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 450fe29

@nullcopy nullcopy merged commit 9e2fa1b into main May 12, 2026
15 checks passed
@nullcopy nullcopy deleted the greg/voting-jni-db-rounds branch May 12, 2026 00:23
@linear

linear Bot commented Jun 1, 2026

Copy link
Copy Markdown

MOB-1109

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants