k = 11;
field = "pallas";

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

witness "ProposeMain" {
    # Proposers total number of governance tokens
    Base total_funds,
    Scalar total_funds_blind,

    # Check the inputs and this proof are for the same token
    Base gov_token_blind,

    # Proposal parameters
    Base proposal_auth_calls_commit,
    Base proposal_creation_blockwindow,
    Base proposal_duration_blockwindows,
    Base proposal_user_data,
    Base proposal_blind,

    # DAO params
    Base dao_proposer_limit,
    Base dao_quorum,
    Base dao_early_exec_quorum,
    Base dao_approval_ratio_quot,
    Base dao_approval_ratio_base,
    Base dao_gov_token_id,
    Base dao_notes_public_x,
    Base dao_notes_public_y,
    Base dao_proposer_secret,
    Base dao_proposals_public_x,
    Base dao_proposals_public_y,
    Base dao_votes_public_x,
    Base dao_votes_public_y,
    Base dao_exec_public_x,
    Base dao_exec_public_y,
    Base dao_early_exec_public_x,
    Base dao_early_exec_public_y,
    Base dao_bulla_blind,

    Uint32 dao_leaf_pos,
    MerklePath dao_path,
}

circuit "ProposeMain" {
    token_commit = poseidon_hash(dao_gov_token_id, gov_token_blind);
    constrain_instance(token_commit);

    # Derive DAO proposer public key
    dao_proposer_public = ec_mul_base(dao_proposer_secret, NULLIFIER_K);
    dao_proposer_public_x = ec_get_x(dao_proposer_public);
    dao_proposer_public_y = ec_get_y(dao_proposer_public);

    dao_bulla = poseidon_hash(
        dao_proposer_limit,
        dao_quorum,
        dao_early_exec_quorum,
        dao_approval_ratio_quot,
        dao_approval_ratio_base,
        dao_gov_token_id,
        dao_notes_public_x,
        dao_notes_public_y,
        dao_proposer_public_x,
        dao_proposer_public_y,
        dao_proposals_public_x,
        dao_proposals_public_y,
        dao_votes_public_x,
        dao_votes_public_y,
        dao_exec_public_x,
        dao_exec_public_y,
        dao_early_exec_public_x,
        dao_early_exec_public_y,
        dao_bulla_blind,
    );

    dao_root = merkle_root(dao_leaf_pos, dao_path, dao_bulla);
    constrain_instance(dao_root);
    # Proves this DAO is valid

    proposal_bulla = poseidon_hash(
        proposal_auth_calls_commit,
        proposal_creation_blockwindow,
        proposal_duration_blockwindows,
        proposal_user_data,
        dao_bulla,
        proposal_blind,
    );
    constrain_instance(proposal_bulla);
    constrain_instance(proposal_creation_blockwindow);

    # This is the main check
    # We check that dao_proposer_limit <= total_funds
    one = witness_base(1);
    total_funds_1 = base_add(total_funds, one);
    less_than_strict(dao_proposer_limit, total_funds_1);

    # Pedersen commitment for coin's value
    vcv = ec_mul_short(total_funds, VALUE_COMMIT_VALUE);
    vcr = ec_mul(total_funds_blind, VALUE_COMMIT_RANDOM);
    total_funds_commit = ec_add(vcv, vcr);
    constrain_instance(ec_get_x(total_funds_commit));
    constrain_instance(ec_get_y(total_funds_commit));
}
