Skip to content

CSHLD-1208: Add retention flags when appending commitments in Merkle tree logic#319

Merged
Ranjna-G merged 1 commit into
masterfrom
CSHLD-1208-add-retention-flags
Jul 17, 2026
Merged

CSHLD-1208: Add retention flags when appending commitments in Merkle tree logic#319
Ranjna-G merged 1 commit into
masterfrom
CSHLD-1208-add-retention-flags

Conversation

@Ranjna-G

Copy link
Copy Markdown
Contributor

Summary

Threads per-commitment ownership booleans from the proto wire format through the Rust shardtree append path, assigning Retention::Marked to owned leaves so the shardtree preserves their witness paths for future inclusion-proof generation.

Linear: CSHLD-1208

Changes

  • proto/privacy_coin.proto: add repeated bool owned = 4 to AppendCommitmentsRequest
  • src/zcash/tree.rs: accept owned: Vec<bool>; assign Marking::Marked for owned leaves, Marking::None otherwise
  • src/lib.rs: extract req.owned and pass to tree.append_commitments
  • ShieldedMerkleTree.java: add List<Boolean> owned parameter to appendCommitments; removed backward-compatible overloads
  • ShieldedMerkleTreeTest.java: add f-flag assertions verifying MARKED (f=2) and CHECKPOINT|MARKED (f=3) on owned leaves
  • pom.xml: add jackson-databind test-scoped dependency for JSON tree state parsing in tests

Test Plan

  • make jar rebuilds the WASM binary with the Rust changes
  • make test-java runs ShieldedMerkleTreeTest including the two new retention-flag tests
  • Existing 33 tests must continue to pass

CLOSES TICKET: CSHLD-1208

@linear-code

linear-code Bot commented Jul 16, 2026

Copy link
Copy Markdown

CSHLD-1208

@Ranjna-G
Ranjna-G marked this pull request as ready for review July 16, 2026 12:37
@Ranjna-G
Ranjna-G requested a review from a team as a code owner July 16, 2026 12:37
Comment on lines +5 to +6
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

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.

where does json come from here? I though we were using protobuf for WASM communication?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This isn't WASM communication - tree.save() returns the internal Rust PersistedShardTreeState serialized by the shardtree crate via serde_json. We're just parsing it in the test to assert retention flags on individual leaves.

Replaced JsonNode with Jackson-annotated classes

@Ranjna-G
Ranjna-G force-pushed the CSHLD-1208-add-retention-flags branch from 31b7b1b to bbd8fba Compare July 17, 2026 06:57
@Ranjna-G
Ranjna-G enabled auto-merge July 17, 2026 07:03

@OttoAllmendinger OttoAllmendinger 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.

Overall solid, focused change with CI green. Left three comments: a silent-truncation risk in the owned vs commitments length handling, a breaking API/README-staleness note on the removed Java overloads, and a suggestion to move the retention-flag test coverage into Rust rather than asserting on the (supposedly opaque) persisted JSON from Java.


Generated by Claude Code

marking: Marking::None,
marking: if is_owned {
Marking::Marked
} else {

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.

No length validation between owned and commitments: owned.get(i).copied().unwrap_or(false) silently treats an out-of-range index as "not owned". That's fine for a shorter/absent owned vec (matches the proto doc), but a caller passing a longer or misaligned owned vec (e.g. an off-by-one upstream) fails silently instead of erroring, and could mis-mark ownership for a real block. Consider validating owned.len() == commitments.len() (or <=) up front and returning an Err otherwise.

Also: there's no Rust-level unit test for this logic (there are no #[cfg(test)] tests anywhere in tree.rs/this crate). The new retention-flag behavior is only exercised indirectly through Java, via JSON round-trip through the WASM boundary — see the review comment on ShieldedMerkleTreeTest.java for why that's the wrong layer to test this in.


Generated by Claude Code

long blockHeight, List<ShieldedCommitment> commitments, ShieldedRoot expectedRoot) {
long blockHeight, List<ShieldedCommitment> commitments, List<Boolean> owned,
ShieldedRoot expectedRoot) {
requireU32(blockHeight, "blockHeight");

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.

Removing the 2-arg and 3-arg appendCommitments overloads is a breaking API change for any external caller. Worth calling out explicitly in the PR description (not just implied by the diff), and confirming downstream consumers are updated in lockstep.

Separately: packages/wasm-privacy-coin/README.md (lines ~163-164, 278, 280, 290, 302, 316-317) still documents and uses the old 2-arg/3-arg signatures — those examples no longer compile against this new signature and should be updated in this PR.


Generated by Claude Code

* <ul>
* <li>CMX (i=0, owned, not last) → f=2 MARKED
* <li>CMX_2 (i=1, not owned, not last) → f=0 EPHEMERAL
* <li>CMX_3 (i=2, owned, last) → f=3 CHECKPOINT|MARKED

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.

These new tests assert on the persisted tree JSON's internal shape (shard/cap/Leaf/Parent nodes, f/h fields) via a hand-rolled Jackson POJO hierarchy — but TreeState's own doc explicitly says "the internal encoding is an implementation detail; do not interpret the bytes directly." Testing it from Java means the assertion travels through JSON serialization, the WASM ABI, and protobuf/Jackson decoding — none of which is the thing actually being verified (retention-flag assignment in tree.rs), and any of which could mask or introduce unrelated failures. It also means a shardtree crate serde format change surfaces as a confusing Java test failure two layers removed from the actual cause.

Suggest moving this coverage into a Rust unit test in tree.rs (there currently are none in this crate) that calls append_commitments and asserts directly on extract_state()'s returned struct (or the in-memory tree) — no JSON/WASM/Jackson round-trip required. The Java-side tests could then stay black-box (leaf count, root correctness) rather than reaching into the opaque internal format.


Generated by Claude Code

Per-commitment ownership booleans are now threaded from the proto wire
format into the Rust shardtree append path. Owned leaves are assigned
Retention::Marked so the shardtree preserves their witness paths;
non-owned leaves remain Retention::Ephemeral (or Checkpoint for the
last commitment in a block).

Ticket: CSHLD-1208
@Ranjna-G
Ranjna-G force-pushed the CSHLD-1208-add-retention-flags branch from bbd8fba to 4905aac Compare July 17, 2026 09:12
}

#[cfg(test)]
mod tests {

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.

👍

@Ranjna-G
Ranjna-G merged commit d12e49b into master Jul 17, 2026
13 checks passed
@Ranjna-G
Ranjna-G deleted the CSHLD-1208-add-retention-flags branch July 17, 2026 09:24
Comment on lines +44 to +49
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
<scope>test</scope>
</dependency>

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.

actually now you don't need this any longer

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.

2 participants