k = 13; field = "pallas"; constant "Burn" { EcFixedPointShort VALUE_COMMIT_VALUE, EcFixedPoint VALUE_COMMIT_RANDOM, EcFixedPointBase NULLIFIER_K, } witness "Burn" { Base secret, Base serial, Base value, Base token, Scalar value_blind, Scalar token_blind, Uint32 leaf_pos, MerklePath path, Base signature_secret, } circuit "Burn" { # Poseidon hash of the nullifier nullifier = poseidon_hash(secret, serial); constrain_instance(nullifier); # Pedersen commitment for coin's value vcv = ec_mul_short(value, VALUE_COMMIT_VALUE); vcr = ec_mul(value_blind, VALUE_COMMIT_RANDOM); value_commit = ec_add(vcv, vcr); # Since value_commit is a curve point, we fetch its coordinates # and constrain them: value_commit_x = ec_get_x(value_commit); value_commit_y = ec_get_y(value_commit); constrain_instance(value_commit_x); constrain_instance(value_commit_y); # Pedersen commitment for coin's token ID tcv = ec_mul_base(token, NULLIFIER_K); tcr = ec_mul(token_blind, VALUE_COMMIT_RANDOM); token_commit = ec_add(tcv, tcr); # Since token_commit is also a curve point, we'll do the same # coordinate dance: token_commit_x = ec_get_x(token_commit); token_commit_y = ec_get_y(token_commit); constrain_instance(token_commit_x); constrain_instance(token_commit_y); # Coin hash pub = ec_mul_base(secret, NULLIFIER_K); pub_x = ec_get_x(pub); pub_y = ec_get_y(pub); C = poseidon_hash(pub_x, pub_y, value, token, serial); # Merkle root root = merkle_root(leaf_pos, path, C); constrain_instance(root); # Finally, we derive a public key for the signature and # constrain its coordinates: signature_public = ec_mul_base(signature_secret, NULLIFIER_K); signature_x = ec_get_x(signature_public); signature_y = ec_get_y(signature_public); constrain_instance(signature_x); constrain_instance(signature_y); # At this point we've enforced all of our public inputs. }