k = 11; field = "pallas"; constant "Fee_V1" { EcFixedPointShort VALUE_COMMIT_VALUE, EcFixedPoint VALUE_COMMIT_RANDOM, EcFixedPointBase NULLIFIER_K, } witness "Fee_V1" { # Secret key used to derive input's nullifier Base input_secret, # Input coin's leaf position in the Merkle tree of coins Uint32 input_leaf_pos, # Merkle path to the coin MerklePath input_path, # Secret key used to derive public key for the tx signature Base signature_secret, # Value of the input coin Base input_value, # Random blinding factor for the input value commitment Scalar input_value_blind, # Input coin's spend hook Base input_spend_hook, # Data passed from the input to the invoked contract Base input_user_data, # Unique coin blind corresponding to the input coin Base input_coin_blind, # Blinding factor for the encrypted user_data Base input_user_data_blind, # Value of the output coin Base output_value, # Output coin's spend hook Base output_spend_hook, # Data passed from the output coin to the invoked contract Base output_user_data, # Random blinding factor for the output value commitment Scalar output_value_blind, # Unique coin blind corresponding to the output coin Base output_coin_blind, # Token ID Base token, # Random blinding factor for the token ID Base token_blind, } circuit "Fee_V1" { # Derive the input coin pub = ec_mul_base(input_secret, NULLIFIER_K); pub_x = ec_get_x(pub); pub_y = ec_get_y(pub); input_coin = poseidon_hash( pub_x, pub_y, input_value, token, input_spend_hook, input_user_data, input_coin_blind, ); nullifier = poseidon_hash(input_secret, input_coin); constrain_instance(nullifier); # Pedersen commitment for the input coin value input_vcv = ec_mul_short(input_value, VALUE_COMMIT_VALUE); input_vcr = ec_mul(input_value_blind, VALUE_COMMIT_RANDOM); input_value_commit = ec_add(input_vcv, input_vcr); constrain_instance(ec_get_x(input_value_commit)); constrain_instance(ec_get_y(input_value_commit)); # Commitment for the token ID token_commit = poseidon_hash(token, token_blind); constrain_instance(token_commit); # Merkle root root = merkle_root(input_leaf_pos, input_path, input_coin); constrain_instance(root); # Export user_data user_data_enc = poseidon_hash(input_user_data, input_user_data_blind); constrain_instance(user_data_enc); # Reveal spend_hook ZERO = witness_base(0); constrain_equal_base(input_spend_hook, ZERO); # Derive a public key for the signature and # constrain its coordinates signature_public = ec_mul_base(signature_secret, NULLIFIER_K); constrain_instance(ec_get_x(signature_public)); constrain_instance(ec_get_y(signature_public)); # Derive output coin output_coin = poseidon_hash( pub_x, pub_y, output_value, token, output_spend_hook, output_user_data, output_coin_blind, ); constrain_instance(output_coin); # Pedersen commitment for the output coin value output_vcv = ec_mul_short(output_value, VALUE_COMMIT_VALUE); output_vcr = ec_mul(output_value_blind, VALUE_COMMIT_RANDOM); output_value_commit = ec_add(output_vcv, output_vcr); constrain_instance(ec_get_x(output_value_commit)); constrain_instance(ec_get_y(output_value_commit)); }