vote_commitment_tree/lib.rs
1//! Append-only Poseidon Merkle tree for the Vote Commitment Tree (Gov Steps V1).
2//!
3//! This tree holds both **Vote Authority Notes (VANs)** and **Vote Commitments (VCs)** as leaves.
4//! Domain separation (DOMAIN_VAN / DOMAIN_VC) is applied when *constructing* leaf values
5//! (in circuits / chain); this crate stores and hashes already-committed field elements.
6//!
7//! Insertion order (per cosmos-sdk-messages-spec):
8//! - `MsgDelegateVote` → append 1 leaf (VAN)
9//! - `MsgCastVote` → append 2 leaves (new VAN, then VC)
10//!
11//! ## Architecture
12//!
13//! The crate is split into server and client layers with a sync API boundary:
14//!
15//! - **Shared types** ([`MerkleHashVote`], [`Anchor`], [`MerklePath`]) — used by both sides.
16//! - **[`TreeServer`]** — authoritative full tree: append, checkpoint, serve data via [`TreeSyncApi`].
17//! - **[`TreeClient`]** — sparse tree: sync from server, mark positions, generate witnesses.
18//! - **[`TreeSyncApi`]** — trait defining the communication boundary (in-process for POC,
19//! maps to Cosmos SDK endpoints in production).
20//!
21//! Built on `incrementalmerkletree` / `shardtree` (same crates that back Orchard's
22//! note commitment tree), with two substitutions:
23//! - **Hash:** Poseidon (no layer tagging) instead of Sinsemilla
24//! - **Empty leaf:** `poseidon_hash(0, 0)` instead of `Fp::from(2)`
25
26// -- Modules ---------------------------------------------------------------
27
28mod anchor;
29pub mod client;
30mod hash;
31pub mod kv_shard_store;
32pub mod memory_server;
33mod path;
34pub mod serde;
35pub mod server;
36pub mod sync_api;
37
38// -- Re-exports (public API) -----------------------------------------------
39
40pub use anchor::Anchor;
41pub use client::{SyncError, TreeClient};
42pub use hash::{MerkleHashVote, TREE_DEPTH};
43pub use path::{MerklePath, MERKLE_PATH_BYTES};
44pub use server::{AppendFromKvError, MemoryTreeServer, SyncableServer, TreeServer};
45pub use sync_api::TreeSyncApi;
46
47// -- Shared utilities ------------------------------------------------------
48
49use pasta_curves::Fp;
50
51/// Domain tag for Vote Commitments (matches `orchard::vote_proof::circuit::DOMAIN_VC`).
52pub const DOMAIN_VC: u64 = 1;
53
54/// Poseidon hash of two field elements (delegates to imt-tree for circuit consistency).
55#[inline]
56pub fn poseidon_hash(left: Fp, right: Fp) -> Fp {
57 imt_tree::poseidon_hash(left, right)
58}
59
60/// Poseidon hash of six field elements (`ConstantLength<6>`, width 3, rate 2).
61pub fn poseidon_hash_6(a: Fp, b: Fp, c: Fp, d: Fp, e: Fp, f: Fp) -> Fp {
62 use halo2_gadgets::poseidon::primitives::{self as poseidon, ConstantLength, P128Pow5T3};
63
64 poseidon::Hash::<_, P128Pow5T3, ConstantLength<6>, 3, 2>::init().hash([a, b, c, d, e, f])
65}