constant "DaoProposeMain" {
	EcFixedPointShort VALUE_COMMIT_VALUE,
	EcFixedPoint VALUE_COMMIT_RANDOM,
}

contract "DaoProposeMain" {
    # Proposers total number of gov tokens
    Base total_funds,
    Scalar total_funds_blind,

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

    # proposal params
    Base proposal_dest_x,
    Base proposal_dest_y,
    Base proposal_amount,
    Base proposal_serial,
    Base proposal_token_id,
    Base proposal_blind,

    # DAO params
    Base dao_proposer_limit,
    Base dao_quorum,
    Base dao_approval_ratio_quot,
    Base dao_approval_ratio_base,
    Base gov_token_id,
    Base dao_public_x,
    Base dao_public_y,
    Base dao_bulla_blind,

	Uint32 dao_leaf_pos,
	MerklePath dao_path,
}

circuit "DaoProposeMain" {
    token_commit = poseidon_hash(gov_token_id, gov_token_blind);
	constrain_instance(token_commit);

    dao_bulla = poseidon_hash(
        dao_proposer_limit,
        dao_quorum,
        dao_approval_ratio_quot,
        dao_approval_ratio_base,
        gov_token_id,
        dao_public_x,
        dao_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_dest_x,
        proposal_dest_y,
        proposal_amount,
        proposal_serial,
        proposal_token_id,
        dao_bulla,
        proposal_blind,
        # @tmp-workaround
        proposal_blind,
    );
    constrain_instance(proposal_bulla);

    # Rangeproof check for proposal amount
    zero = witness_base(0);
    less_than(zero, proposal_amount);

    # 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(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);
	# Since total_funds_commit is a curve point, we fetch its coordinates
	# and constrain them:
	total_funds_commit_x = ec_get_x(total_funds_commit);
	total_funds_commit_y = ec_get_y(total_funds_commit);
	constrain_instance(total_funds_commit_x);
	constrain_instance(total_funds_commit_y);
}

