k = 14;
field = "pallas";

constant "VoteInput" {
    EcFixedPointBase NULLIFIER_K,
    EcFixedPoint VALUE_COMMIT_RANDOM,
    EcFixedPointShort VALUE_COMMIT_VALUE,
}

witness "VoteInput" {
    Base coin_secret,
    Base coin_value,
    Base coin_gov_token_id,
    Base coin_spend_hook,
    Base coin_user_data,
    Base coin_blind,

    Base proposal_bulla,

    Scalar value_blind,
    Base gov_token_blind,

    Uint32 leaf_pos,
    MerklePath coin_path,

    SparseMerklePath null_path,

    Base signature_secret,
}

circuit "VoteInput" {
    pub = ec_mul_base(coin_secret, NULLIFIER_K);
    pub_x = ec_get_x(pub);
    pub_y = ec_get_y(pub);
    coin = poseidon_hash(
        pub_x,
        pub_y,
        coin_value,
        coin_gov_token_id,
        coin_spend_hook,
        coin_user_data,
        coin_blind,
    );

    # We need this to detect whether the above coin was already spent.
    # Use a SMT, and show that at this position, the leaf is ZERO
    ZERO = witness_base(0);
    nullifier = poseidon_hash(coin_secret, coin);
    null_tree_root = sparse_merkle_root(
        nullifier,              # Position
        null_path,              # Path to root
        ZERO,                   # Leaf value
    );
    constrain_instance(null_tree_root);

    # Include some secret information in vote nullifier to defeat correlation
    # attacks. We reveal the proposal_bulla in vote-main.zk as well.
    vote_nullifier = poseidon_hash(nullifier, coin_secret, proposal_bulla);
    constrain_instance(proposal_bulla);
    constrain_instance(vote_nullifier);

    vcv = ec_mul_short(coin_value, VALUE_COMMIT_VALUE);
    vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
    coin_value_commit = ec_add(vcv, vcr);
    constrain_instance(ec_get_x(coin_value_commit));
    constrain_instance(ec_get_y(coin_value_commit));

    token_commit = poseidon_hash(coin_gov_token_id, gov_token_blind);
    constrain_instance(token_commit);

    # Merkle root
    merkle_coin_root = merkle_root(leaf_pos, coin_path, coin);
    constrain_instance(merkle_coin_root);

    signature_public = ec_mul_base(signature_secret, NULLIFIER_K);
    constrain_instance(ec_get_x(signature_public));
    constrain_instance(ec_get_y(signature_public));
}
