Skip to content

Instantly share code, notes, and snippets.

@10to4
Last active January 21, 2024 17:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 10to4/8136e021243ec3e52fc99657ba6315ca to your computer and use it in GitHub Desktop.
Save 10to4/8136e021243ec3e52fc99657ba6315ca to your computer and use it in GitHub Desktop.
puzzle-gamma-ray

Firstly, in this code, a circuit verification is performed using Groth16. The logic of the circuit is to verify the Merkle proof of the second leaf node of a Merkle tree with four leaf nodes, as well as the hash value (nullifier) of this leaf node. The value of this leaf node is derived from the x-value of an elliptic curve point obtained by scalar multiplication on G1, using a secret value as the scalar value. All values on the Scalar Field are defined as scalar values on MNT4, while G1 is defined as the Base point on MNT6.

The intention of this task is to construct a different value secret_hack to replace the secret, whose hash value nullifier_hack is different from the original secret's hash value nullifier, and can still pass the circuit verification when secret_hack and nullifier_hack are input.

First, since the hash value nullifier_hack of secret_hack must be different from the hash value nullifier of the secret, it implies that secret_hack and secret cannot be the same. Then, as the secret needs to be used as a scalar value to perform scalar multiplication on G1 to obtain the x-value of the elliptic curve point (defined as pointA), if a secret_hack value can be obtained such that the x-value of the elliptic curve point (defined as pointB) obtained by performing scalar multiplication of secret_hack on G1 is the same as the x-value of pointA, the circuit verification can be passed.

let base = G1Var::new_constant(ark_relations::ns!(cs, "base"), G1Affine::generator())?;
let pk = base.scalar_mul_le(secret_bits.iter())?.to_affine()?;

// Allocate Leaf
let leaf_g: Vec<_> = vec![pk.x];

On the elliptic curve, if pointA.x = pointB.x, it indicates that pointA is the same as pointB, or pointA.y = - pointB.y. Therefore, if we can find a way to construct a pointB, such that it is the symmetric point of pointA, we can achieve the final goal.

Since pointA = base^secret, then pointB = base^(-secret), i.e., secret_hack = -secret = r_6 - secret. Here, r_6 is the order of the Scalar Field on the MNT6 curve. And all Scalar Field values in the code are represented on the Scalar Field of MNT4. Therefore, it is necessary to convert the value of r_6 - secret on the Scalar Field of MNT6 to the value on the Scalar Field of MNT4. The parameters are as follows; the orders r of the two Scalar Fields are different, so it is necessary to convert secret_hack to represent the correct value of secret_hack on the Scalar Field of MNT.

// mnt4
// * Scalar field: r_4 = 0x01C4C62D92C41110229022EEE2CDADB7F997505B8FAFED5EB7E8F96C97D87307FDB925E8A0ED8D99D124D9A15AF79DB26C5C28C859A99B3EEBCA9429212636B9DFF97634993AA4D6C381BC3F0057974EA099170FA13A4FD90776E240000001

//mnt6
// * Scalar field: r_6 = 0x01C4C62D92C41110229022EEE2CDADB7F997505B8FAFED5EB7E8F96C97D87307FDB925E8A0ED8D99D124D9A15AF79DB117E776F218059DB80F0DA5CB537E38685ACCE9767254A4638810719AC425F0E39D54522CDD119F5E9063DE245E8001

secret_hack = r_6 - secret = (r_6 - r_4) + (r_4 - secret) Let delta = r_6 - r_4, then it can be calculated in the following way: let delta = MNT4BigFr::from(MNT6BigFr::from(- 1).into_bigint()) - MNT4BigFr::from(-1); Thus, secret_hack is calculated through the following steps:

let delta = MNT4BigFr::from(-1) - MNT4BigFr::from(MNT6BigFr::from(- 1).into_bigint());
let secret_hack: MNT4BigFr = - leaked_secret - delta;

Then continue to calculate nullifier_hack:

let nullifier_hack = <LeafH as CRHScheme>::evaluate(&leaf_crh_params, vec![secret_hack]).unwrap();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment