# Circuit used to mint arbitrary coins given a mint authority secret.
constant "TokenMint_V1" {
	EcFixedPointShort VALUE_COMMIT_VALUE,
	EcFixedPoint VALUE_COMMIT_RANDOM,
	EcFixedPointBase NULLIFIER_K,
}

contract "TokenMint_V1" {
	# Token mint authority secret
	Base mint_authority,
	# Token supply
	Base supply,
	# Recipient's public key x coordinate
	Base rcpt_x,
	# Recipient's public key y coordinate
	Base rcpt_y,
	# Unique serial number for the minted coin
	Base serial,
	# Random blinding factor for the minted coin
	Base coin_blind,
	# Allows composing this ZK proof to invoke other contracts
	Base spend_hook,
	# Data passed from this coin to the invoked contract
	Base user_data,
	# Random blinding factor for the value commitment
	Scalar value_blind,
	# Random blinding factor for the token ID
	Scalar token_blind,
}

circuit "TokenMint_V1" {
	# Derive public key for the mint authority
	mint_public = ec_mul_base(mint_authority, NULLIFIER_K);
	mint_x = ec_get_x(mint_public);
	mint_y = ec_get_y(mint_public);
	# I don't think we need to have these two as public inputs
	#constrain_instance(mint_x);
	#constrain_instance(mint_y);

	# Derive the token ID
	token_id = poseidon_hash(mint_x, mint_y);
	constrain_instance(token_id);

	# Poseidon hash of the minted coin
	C = poseidon_hash(
		rcpt_x,
		rcpt_y,
		supply,
		token_id,
		serial,
		spend_hook,
		user_data,
		coin_blind,
	);
	constrain_instance(C);

	# Pedersen commitment for the coin's value
	vcv = ec_mul_short(supply, VALUE_COMMIT_VALUE);
	vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM);
	value_commit = ec_add(vcv, vcr);
	constrain_instance(ec_get_x(value_commit));
	constrain_instance(ec_get_y(value_commit));

	# Pedersen commitment for the token ID
	tcv = ec_mul_base(token_id, NULLIFIER_K);
	tcr = ec_mul(token_blind, VALUE_COMMIT_RANDOM);
	token_commit = ec_add(tcv, tcr);
	constrain_instance(ec_get_x(token_commit));
	constrain_instance(ec_get_y(token_commit));
}
