Переглянути джерело

added bytes buffer to asset_id in mint/spend

lunar-mining 4 роки тому
батько
коміт
ddf3535852
5 змінених файлів з 167 додано та 488 видалено
  1. 8 7
      proofs/mint.pism
  2. 0 409
      proofs/mint2.psm
  3. 8 7
      proofs/spend.pism
  4. 117 60
      src/circuit/mint_contract.rs
  5. 34 5
      src/circuit/spend_contract.rs

+ 8 - 7
proofs/mint.pism

@@ -9,7 +9,7 @@ constant CRH_IVK BlakePersonalization
 contract mint_contract
     # Value commitment
     param value U64
-    param asset_id U64
+    param asset_id Fr
     param randomness_value Fr
     param randomness_asset Fr
 
@@ -19,7 +19,7 @@ contract mint_contract
 start
     # Witness input values
     u64_as_binary_le value param:value
-    u64_as_binary_le asset_id param:asset_id
+    fr_as_binary_le asset_id param:asset_id
     fr_as_binary_le randomness_value param:randomness_value
     fr_as_binary_le randomness_asset param:randomness_asset
     fr_as_binary_le serial param:serial
@@ -60,9 +60,6 @@ start
     # value
     binary_extend preimage value
 
-    # asset_id
-    binary_extend preimage asset_id
-
 # Fr values are 252 bits so we need to pad it with extra 0s
 # to match the Rust values which are 256 bits
 {% macro binary_put_fr(binary, var) -%}
@@ -79,12 +76,16 @@ start
     # randomness_coin
     {{ binary_put_fr("preimage", "randomness_coin") }}
 
+    # asset_id
+    {{ binary_put_fr("preimage", "asset_id") }}
+
     # Public key:       SubgroupPoint   = 256 bits
     # Value:            u64             = 64 bits
+    # AssetID:          Fr              = 252 + 4 bits padding
     # Serial:           Fr              = 252 + 4 bits padding
     # Randomness coin   Fr              = 252 + 4 bits padding
-    # TOTAL: 896 bits for preimage
-    static_assert_binary_size preimage 896
+    # TOTAL: 1088 bits for preimage
+    static_assert_binary_size preimage 1088
     blake2s coin preimage CRH_IVK
     emit_binary coin
 end

+ 0 - 409
proofs/mint2.psm

@@ -1,409 +0,0 @@
-constant edwards_d 0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1
-constant one 0x0000000000000000000000000000000000000000000000000000000000000001
-constant zero 0x0000000000000000000000000000000000000000000000000000000000000000
-constant G_VCR_u 0x6800f4fa0f001cfc7ff6826ad58004b4d1d8da41af03744e3bce3b7793664337
-constant G_VCR_v 0x6d81d3a9cb45dedbe6fb2a6e1e22ab50ad46f1b0473b803b3caefab9380b6a8b
-constant G_VCV_u 0x273f910d9ecc1615d8618ed1d15fef4e9472c89ac043042d36183b2cb4d7ef51
-constant G_VCV_v 0x466a7e3a82f67ab1d32294fd89774ad6bc3332d0fa1ccd18a77a81f50667c8d7
-
-{% macro square(x2, x) %}
-    ########################################################
-    # square({{x2}}, {{x}})
-    ########################################################
-    private {{x2}}
-    set {{x2}} {{x}}
-    mul {{x2}} {{x}}
-
-    lc0_add {{x}}
-    lc1_add {{x}}
-    lc2_add {{x2}}
-    enforce
-{% endmacro %}
-
-{% macro jubjub_witness(p, u, v) %}
-    ########################################################
-    # jubjub_witness({{p}}, {{u}}, {{v}})
-    ########################################################
-    # -u^2 + v^2 = 1 + du^2v^2
-    {{ square(p + "_u2", u) }}
-    {{ square(p + "_v2", v) }}
-    private {{p}}_u2v2
-    set {{p}}_u2v2 {{p + "_u2"}}
-    mul {{p}}_u2v2 {{p + "_v2"}}
-    # on curve check
-    lc0_sub {{p + "_u2"}}
-    lc0_add {{p + "_v2"}}
-    lc1_add_one
-    lc2_add_one
-    lc2_add_coeff edwards_d {{p}}_u2v2
-    enforce
-{% endmacro %}
-
-{% macro jubjub_double(p, u, v) %}
-    ########################################################
-    # jubjub_double({{p}}, {{u}}, {{v}})
-    ########################################################
-
-    # Compute T = (u + v) * (v - EDWARDS_A*u)
-    #           = (u + v) * (u + v)
-    private {{p}}_t
-    set {{p}}_t {{u}}
-    add {{p}}_t {{v}}
-    local {{p}}_t1
-    set {{p}}_t1 {{u}}
-    add {{p}}_t1 {{v}}
-    mul {{p}}_t {{p}}_t1
-
-    lc0_add {{u}}
-    lc0_add {{v}}
-    lc1_add {{u}}
-    lc1_add {{v}}
-    lc2_add {{p}}_t
-    enforce
-
-    # Compute A = u * v
-    private {{p}}_A
-    set {{p}}_A {{u}}
-    mul {{p}}_A {{v}}
-
-    # Compute C = d*A*A
-    private {{p}}_C
-    load {{p}}_C edwards_d
-    mul {{p}}_C {{p}}_A
-    mul {{p}}_C {{p}}_A
-
-    lc0_add_coeff edwards_d {{p}}_A
-    lc1_add {{p}}_A
-    lc2_add {{p}}_C
-    enforce
-
-    # Compute u3 = (2.A) / (1 + C)
-    private {{p}}_u
-    set {{p}}_u {{p}}_A
-    add {{p}}_u {{p}}_A
-    local {{p}}_u3_t1
-    load {{p}}_u3_t1 one
-    add {{p}}_u3_t1 {{p}}_C
-    divide {{p}}_u {{p}}_u3_t1
-
-    lc0_add_one
-    lc0_add {{p}}_C
-    lc1_add {{p}}_u
-    lc2_add {{p}}_A
-    lc2_add {{p}}_A
-    enforce
-
-    # Compute v3 = (T + (EDWARDS_A-1)*A) / (1 - C)
-    #            = (T - 2.A) / (1 - C)
-    private {{p}}_v
-    set {{p}}_v {{p}}_t
-    local {{p}}_2A
-    set {{p}}_2A {{p}}_A
-    add {{p}}_2A {{p}}_A
-    sub {{p}}_v {{p}}_2A
-    local {{p}}_v3_t1
-    load {{p}}_v3_t1 one
-    sub {{p}}_v3_t1 {{p}}_C
-    divide {{p}}_v {{p}}_v3_t1
-
-    lc0_add_one
-    lc0_sub {{p}}_C
-    lc1_add {{p}}_v
-    lc2_add {{p}}_t
-    lc2_sub {{p}}_A
-    lc2_sub {{p}}_A
-    enforce
-{% endmacro %}
-
-{% macro jubjub_assert_not_small_order(p, u, v) %}
-    ########################################################
-    # jubjub_assert_not_small_order({{p}}, {{u}}, {{v}})
-    ########################################################
-
-    # First doubling
-    {{ jubjub_double(p + "1", u, v) }}
-    # Second doubling
-    {{ jubjub_double(p + "2", p + "1_u", p + "1_v") }}
-    # Third doubling
-    {{ jubjub_double(p + "3", p + "2_u", p + "2_v") }}
-
-    # (0, -1) is a small order point, but won't ever appear here
-    # because cofactor is 2^3, and we performed three doublings.
-    # (0, 1) is the neutral element, so checking if u is nonzero
-    # is sufficient to prevent small order points here.
-
-    # Check u != 0
-
-    # Constrain a * inv = 1, which is only valid
-    # iff a has a multiplicative inverse, untrue
-    # for zero.
-    private {{p}}_u3_inv
-    set {{p}}_u3_inv {{p}}3_u
-    invert {{p}}_u3_inv
-
-    lc0_add {{p}}3_u
-    lc1_add {{p}}_u3_inv
-    lc2_add_one
-    enforce
-{% endmacro %}
-
-{% macro jubjub_add(P, x1, y1, x2, y2) %}
-    ########################################################
-    # jubjub_add({{P}}, {{x1}}, {{y1}}, {{x2}}, {{y2}})
-    ########################################################
-
-    # Compute U = (x1 + y1) * (y2 - EDWARDS_A*x2)
-    #           = (x1 + y1) * (x2 + y2)
-    private {{P}}_U
-    set {{P}}_U {{ x1 }}
-    add {{P}}_U {{ y1 }}
-    local {{P}}_tmp
-    set {{P}}_tmp {{ x2 }}
-    add {{P}}_tmp {{ y2 }}
-    mul {{P}}_U {{P}}_tmp
-
-    # assert (x1 + y1) * (x2 + y2) == U
-    lc0_add {{ x1 }}
-    lc0_add {{ y1 }}
-    lc1_add {{ x2 }}
-    lc1_add {{ y2 }}
-    lc2_add {{P}}_U
-    enforce
-
-    # Compute A = y2 * x1
-    private {{P}}_A
-    set {{P}}_A {{ y2 }}
-    mul {{P}}_A {{ x1 }}
-    # Compute B = x2 * y1
-    private {{P}}_B
-    set {{P}}_B {{ x2 }}
-    mul {{P}}_B {{ y1 }}
-    # Compute C = d*A*B
-    private {{P}}_C
-    load {{P}}_C edwards_d
-    mul {{P}}_C {{P}}_A
-    mul {{P}}_C {{P}}_B
-
-    # assert (d * A) * (B) == C
-    lc0_add_coeff edwards_d {{P}}_A
-    lc1_add {{P}}_B
-    lc2_add {{P}}_C
-    enforce
-
-    # Compute P.x = (A + B) / (1 + C)
-    private {{P}}_u
-    set {{P}}_u {{P}}_A
-    add {{P}}_u {{P}}_B
-    local {{P}}_u_denom
-    load {{P}}_u_denom one
-    add {{P}}_u_denom {{P}}_C
-    divide {{P}}_u {{P}}_u_denom
-
-    lc0_add_one
-    lc0_add {{P}}_C
-    lc1_add {{P}}_u
-    lc2_add {{P}}_A
-    lc2_add {{P}}_B
-    enforce
-
-    # Compute P.y = (U - A - B) / (1 - C)
-    private {{P}}_v
-    set {{P}}_v {{P}}_U
-    sub {{P}}_v {{P}}_A
-    sub {{P}}_v {{P}}_B
-    local {{P}}_v_denom
-    load {{P}}_v_denom one
-    sub {{P}}_v_denom {{P}}_C
-    divide {{P}}_v {{P}}_v_denom
-
-    lc0_add_one
-    lc0_sub {{P}}_C
-    lc1_add {{P}}_v
-    lc2_add {{P}}_U
-    lc2_sub {{P}}_A
-    lc2_sub {{P}}_B
-    enforce
-{% endmacro %}
-
-{% macro jubjub_conditionally_select(p, u, v, condition) %}
-    ########################################################
-    # jubjub_conditionally_select({{p}}, {{u}}, {{v}}, {{condition}})
-    ########################################################
-
-    # Compute u' = self.u if condition, and 0 otherwise
-    private {{p}}_u
-    set {{p}}_u {{u}}
-    mul {{p}}_u {{condition}}
-
-    # condition * u = u'
-    # if condition is 0, u' must be 0
-    # if condition is 1, u' must be u
-    lc0_add {{u}}
-    lc1_add {{condition}}
-    lc2_add {{p}}_u
-    enforce
-
-    # Compute v' = self.v if condition, and 1 otherwise
-    # v' = condition * v + 1 - condition
-    private {{p}}_v
-    set {{p}}_v {{v}}
-    mul {{p}}_v {{condition}}
-    local {{p}}_one
-    load {{p}}_one one
-    add {{p}}_v {{p}}_one
-    sub {{p}}_v {{condition}}
-
-    # condition * v = v' - (1 - condition)
-    # if condition is 0, v' must be 1
-    # if condition is 1, v' must be v
-    lc0_add {{v}}
-    lc1_add {{condition}}
-    lc2_add {{p}}_v
-    lc2_sub_one
-    lc2_add {{condition}}
-    enforce
-{% endmacro %}
-
-{% macro jubjub_mul(p, u, v, x, n) %}
-    ########################################################
-    # jubjub_mul({{p}}, {{u}}, {{v}}, {{x}}, {{n}})
-    ########################################################
-    # Performs a scalar multiplication of this twisted Edwards
-    # point by a scalar represented as a sequence of booleans
-    # in little-endian bit order.
-    
-    {% for i in range(n) %}
-        {% if i == 0 %}
-            {{ jubjub_conditionally_select(
-                p + "_this_base_" + i|string,
-                u,
-                v,
-                x + "_" + i|string
-            ) }}
-
-            debug {{x + "_" + i|string}}
-            debug {{p + "_this_base_" + i|string}}_u
-            debug {{p + "_this_base_" + i|string}}_v
-        {% else %}
-            {{ jubjub_conditionally_select(
-                p + "_this_base_" + i|string,
-                p + "_currbase_" + i|string + "_u",
-                p + "_currbase_" + i|string + "_v",
-                x + "_" + i|string
-            ) }}
-
-            debug {{x + "_" + i|string}}
-            debug {{p + "_this_base_" + i|string}}_u
-            debug {{p + "_this_base_" + i|string}}_v
-        {% endif %}
-
-        {% if i == 0 %}
-            # Do nothing on first round
-        {% elif i == 1 %}
-            {{ jubjub_add(
-                p + "_result_2",
-                p + "_this_base_1_u",
-                p + "_this_base_1_v",
-                p + "_this_base_0_u",
-                p + "_this_base_0_v"
-            ) }}
-
-            debug {{p + "_result_" + (i + 1)|string}}_u
-            debug {{p + "_result_" + (i + 1)|string}}_v
-        {% elif i == (n - 1) %}
-            {{ jubjub_add(
-                p,
-                p + "_this_base_" + i|string + "_u",
-                p + "_this_base_" + i|string + "_v",
-                p + "_result_" + i|string + "_u",
-                p + "_result_" + i|string + "_v",
-            ) }}
-
-            debug {{p}}_u
-            debug {{p}}_v
-        {% else %}
-            {{ jubjub_add(
-                p + "_result_" + (i + 1)|string,
-                p + "_this_base_" + i|string + "_u",
-                p + "_this_base_" + i|string + "_v",
-                p + "_result_" + i|string + "_u",
-                p + "_result_" + i|string + "_v",
-            ) }}
-
-            debug {{p + "_result_" + (i + 1)|string}}_u
-            debug {{p + "_result_" + (i + 1)|string}}_v
-        {% endif %}
-
-        {% if i == 0 %}
-            {{ jubjub_double(
-                p + "_currbase_" + (i + 1)|string,
-                u,
-                v
-            ) }}
-        {% else %}
-            {{ jubjub_double(
-                p + "_currbase_" + (i + 1)|string,
-                p + "_currbase_" + i|string + "_u",
-                p + "_currbase_" + i|string + "_v"
-            ) }}
-        {% endif %}
-    {% endfor %}
-{% endmacro %}
-
-contract mint_contract
-    param public_u
-    param public_v
-    {{ jubjub_witness("public", "public_u", "public_v") }}
-    {{ jubjub_assert_not_small_order("not_small", "public_u", "public_v") }}
-
-    {% for i in range(256) %}
-        param vc_randomness_{{i}}
-
-        lc0_add vc_randomness_{{i}}
-        enforce
-    {% endfor %}
-
-    private g_vcr_u
-    private g_vcr_v
-    load g_vcr_u G_VCR_u
-    load g_vcr_v G_VCR_v
-    {{ jubjub_mul("rcv", "g_vcr_u", "g_vcr_v", "vc_randomness", 256) }}
-
-    public rcvu
-    set rcvu rcv_u
-    lc0_add rcvu
-    lc1_add_one
-    lc2_add rcv_u
-    enforce
-
-    public rcvv
-    set rcvv rcv_v
-    lc0_add rcvv
-    lc1_add_one
-    lc2_add rcv_v
-    enforce
-
-    #############
-    {#
-        {{ jubjub_double("pub_dbl_pre", "public_u", "public_v") }}
-
-        private condition
-        load condition zero
-        {{ jubjub_conditionally_select("pub_dbl", "pub_dbl_pre_u", "pub_dbl_pre_v", "condition") }}
-
-        # Use this code for testing point doubling
-        public dbl_u
-        set dbl_u pub_dbl_u
-        lc0_add dbl_u
-        lc1_add_one
-        lc2_add pub_dbl_u
-        enforce
-        public dbl_v
-        set dbl_v pub_dbl_v
-        lc0_add dbl_v
-        lc1_add_one
-        lc2_add pub_dbl_v
-        enforce
-    #}
-end
-

+ 8 - 7
proofs/spend.pism

@@ -11,7 +11,7 @@ constant NOTE_COMMIT PedersenPersonalization
 contract spend_contract
     # Value commitment
     param value U64
-    param asset_id U64
+    param asset_id Fr
     param randomness_value Fr
     param randomness_asset Fr
 
@@ -27,7 +27,7 @@ contract spend_contract
 start
     # Witness input values
     u64_as_binary_le value param:value
-    u64_as_binary_le asset_id param:asset_id
+    fr_as_binary_le asset_id param:asset_id
     fr_as_binary_le randomness_value param:randomness_value
     fr_as_binary_le randomness_asset param:randomness_asset
 
@@ -99,21 +99,22 @@ start
     # value
     binary_extend preimage value
 
-    # asset_id
-    binary_extend preimage asset_id
-
     # serial
     {{ binary_put_fr("preimage", "serial") }}
 
     # randomness_coin
     {{ binary_put_fr("preimage", "randomness_coin") }}
 
+    # asset_id
+    {{ binary_put_fr("preimage", "asset_id") }}
+
     # Public key:       SubgroupPoint   = 256 bits
     # Value:            u64             = 64 bits
+    # AssetID:          Fr              = 252 + 4 bits padding
     # Serial:           Fr              = 252 + 4 bits padding
     # Randomness coin   Fr              = 252 + 4 bits padding
-    # TOTAL: 896 bits for preimage
-    static_assert_binary_size preimage 896
+    # TOTAL: 1088 bits for preimage
+    static_assert_binary_size preimage 1088
     blake2s coin preimage CRH_IVK
     # Debug stuff. Normally we don't reveal the coin in the spend proof.
     #binary_clone coin2 coin

+ 117 - 60
src/circuit/mint_contract.rs

@@ -1,5 +1,6 @@
 #![allow(unused_imports)]
 #![allow(unused_mut)]
+use crate::crypto::merkle_node::SAPLING_COMMITMENT_TREE_DEPTH;
 use bellman::{
     gadgets::{
         blake2s, boolean,
@@ -27,140 +28,196 @@ impl Circuit<bls12_381::Scalar> for MintContract {
         self,
         cs: &mut CS,
     ) -> Result<(), SynthesisError> {
-        // Line 18: u64_as_binary_le value param:value
+        // Line 20: u64_as_binary_le value param:value
         let value = boolean::u64_into_boolean_vec_le(
-            cs.namespace(|| "Line 18: u64_as_binary_le value param:value"),
+            cs.namespace(|| "Line 20: u64_as_binary_le value param:value"),
             self.value,
         )?;
 
-        // Line 19: u64_as_binary_le asset_id param:asset_id
+        // Line 21: fr_as_binary_le asset_id param:asset_id
         let asset_id = boolean::field_into_boolean_vec_le(
-            cs.namespace(|| "Line 19: u64_as_binary_le asset_id param:asset_id"),
+            cs.namespace(|| "Line 21: fr_as_binary_le asset_id param:asset_id"),
             self.asset_id,
         )?;
 
-        // Line 19: fr_as_binary_le randomness_value param:randomness_value
+        // Line 22: fr_as_binary_le randomness_value param:randomness_value
         let randomness_value = boolean::field_into_boolean_vec_le(
-            cs.namespace(|| "Line 19: fr_as_binary_le randomness_value param:randomness_value"),
+            cs.namespace(|| "Line 22: fr_as_binary_le randomness_value param:randomness_value"),
             self.randomness_value,
         )?;
 
-        // Line 19: fr_as_binary_le randomness_asset param:randomness_asset
+        // Line 23: fr_as_binary_le randomness_asset param:randomness_asset
         let randomness_asset = boolean::field_into_boolean_vec_le(
-            cs.namespace(|| "Line 19: fr_as_binary_le randomness_asset param:randomness_asset"),
+            cs.namespace(|| "Line 23: fr_as_binary_le randomness_asset param:randomness_asset"),
             self.randomness_asset,
         )?;
 
-        // Line 20: fr_as_binary_le serial param:serial
+        // Line 24: fr_as_binary_le serial param:serial
         let serial = boolean::field_into_boolean_vec_le(
-            cs.namespace(|| "Line 20: fr_as_binary_le serial param:serial"),
+            cs.namespace(|| "Line 24: fr_as_binary_le serial param:serial"),
             self.serial,
         )?;
 
-        // Line 21: fr_as_binary_le randomness_coin param:randomness_coin
+        // Line 25: fr_as_binary_le randomness_coin param:randomness_coin
         let randomness_coin = boolean::field_into_boolean_vec_le(
-            cs.namespace(|| "Line 21: fr_as_binary_le randomness_coin param:randomness_coin"),
+            cs.namespace(|| "Line 25: fr_as_binary_le randomness_coin param:randomness_coin"),
             self.randomness_coin,
         )?;
 
-        // Line 23: witness public param:public
+        // Line 27: witness public param:public
         let public = ecc::EdwardsPoint::witness(
-            cs.namespace(|| "Line 23: witness public param:public"),
+            cs.namespace(|| "Line 27: witness public param:public"),
             self.public.map(jubjub::ExtendedPoint::from),
         )?;
 
-        // Line 24: assert_not_small_order public
-        public.assert_not_small_order(cs.namespace(|| "Line 24: assert_not_small_order public"))?;
+        // Line 28: assert_not_small_order public
+        public.assert_not_small_order(cs.namespace(|| "Line 28: assert_not_small_order public"))?;
 
-        // Line 29: ec_mul_const vcv value G_VCV
+        // Line 33: ec_mul_const vcv value G_VCV
         let vcv = ecc::fixed_base_multiplication(
-            cs.namespace(|| "Line 29: ec_mul_const vcv value G_VCV"),
+            cs.namespace(|| "Line 33: ec_mul_const vcv value G_VCV"),
             &zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR,
             &value,
         )?;
 
-        // Line 30: ec_mul_const rcv randomness_value G_VCR
+        // Line 34: ec_mul_const rcv randomness_value G_VCR
         let rcv = ecc::fixed_base_multiplication(
-            cs.namespace(|| "Line 30: ec_mul_const rcv randomness_value G_VCR"),
+            cs.namespace(|| "Line 34: ec_mul_const rcv randomness_value G_VCR"),
             &zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
             &randomness_value,
         )?;
 
-        // Line 31: ec_add cv vcv rcv
-        let cv = vcv.add(cs.namespace(|| "Line 31: ec_add cv vcv rcv"), &rcv)?;
+        // Line 35: ec_add cv vcv rcv
+        let cv = vcv.add(cs.namespace(|| "Line 35: ec_add cv vcv rcv"), &rcv)?;
 
-        // Line 33: emit_ec cv
-        cv.inputize(cs.namespace(|| "Line 33: emit_ec cv"))?;
+        // Line 37: emit_ec cv
+        cv.inputize(cs.namespace(|| "Line 37: emit_ec cv"))?;
 
-        // Line 29: ec_mul_const vca asset_id G_VCV
+        // Line 42: ec_mul_const vca asset_id G_VCV
         let vca = ecc::fixed_base_multiplication(
-            cs.namespace(|| "Line 29: ec_mul_const vca asset_id G_VCV"),
+            cs.namespace(|| "Line 42: ec_mul_const vca asset_id G_VCV"),
             &zcash_proofs::constants::VALUE_COMMITMENT_VALUE_GENERATOR,
             &asset_id,
         )?;
 
-        // Line 47: ec_mul_const rca randomness_asset G_VCR
+        // Line 43: ec_mul_const rca randomness_asset G_VCR
         let rca = ecc::fixed_base_multiplication(
-            cs.namespace(|| "Line 47: ec_mul_const rca randomness_asset G_VCR"),
+            cs.namespace(|| "Line 43: ec_mul_const rca randomness_asset G_VCR"),
             &zcash_proofs::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR,
             &randomness_asset,
         )?;
 
-        // Line 48: ec_add ca vca rca
-        let ca = vca.add(cs.namespace(|| "Line 48: ec_add ca vca rca"), &rca)?;
+        // Line 44: ec_add ca vca rca
+        let ca = vca.add(cs.namespace(|| "Line 44: ec_add ca vca rca"), &rca)?;
 
-        // Line 50: emit_ec ca
-        ca.inputize(cs.namespace(|| "Line 50: emit_ec ca"))?;
+        // Line 46: emit_ec ca
+        ca.inputize(cs.namespace(|| "Line 46: emit_ec ca"))?;
 
-        // Line 39: alloc_binary preimage
+        // Line 53: alloc_binary preimage
         let mut preimage = vec![];
 
-        // Line 42: ec_repr repr_public public
-        let repr_public = public.repr(cs.namespace(|| "Line 42: ec_repr repr_public public"))?;
+        // Line 56: ec_repr repr_public public
+        let repr_public = public.repr(cs.namespace(|| "Line 56: ec_repr repr_public public"))?;
 
-        // Line 43: binary_extend preimage repr_public
+        // Line 57: binary_extend preimage repr_public
         preimage.extend(repr_public);
 
-        // Line 46: binary_extend preimage value
+        // Line 60: binary_extend preimage value
         preimage.extend(value);
 
-        // Line 47: binary_extend preimage asset_id
-        preimage.extend(asset_id);
-
-        // Line 53: binary_extend preimage serial
+        // Line 67: binary_extend preimage serial
         preimage.extend(serial);
 
-        for _ in 0..4 {
-            // Line 55: alloc_const_bit zero_bit false
-            let zero_bit = Boolean::constant(false);
+        // Line 69: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 70: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 72: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 73: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 75: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
 
-            // Line 56: binary_push preimage zero_bit
-            preimage.push(zero_bit);
-        }
+        // Line 76: binary_push preimage zero_bit
+        preimage.push(zero_bit);
 
-        // Line 69: binary_extend preimage randomness_coin
+        // Line 78: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 79: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 83: binary_extend preimage randomness_coin
         preimage.extend(randomness_coin);
 
-        for _ in 0..4 {
-            // Line 71: alloc_const_bit zero_bit false
-            let zero_bit = Boolean::constant(false);
+        // Line 85: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 86: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 88: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 89: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 91: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 92: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 94: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 95: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 99: binary_extend preimage asset_id
+        preimage.extend(asset_id);
+
+        // Line 101: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 102: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 104: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 105: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 107: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 108: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 110: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
 
-            // Line 72: binary_push preimage zero_bit
-            preimage.push(zero_bit);
-        }
+        // Line 111: binary_push preimage zero_bit
+        preimage.push(zero_bit);
 
-        // Line 89: static_assert_binary_size preimage 896
-        assert_eq!(preimage.len(), 896);
+        // Line 120: static_assert_binary_size preimage 1088
+        assert_eq!(preimage.len(), 1088);
 
-        // Line 90: blake2s coin preimage CRH_IVK
+        // Line 121: blake2s coin preimage CRH_IVK
         let mut coin = blake2s::blake2s(
-            cs.namespace(|| "Line 90: blake2s coin preimage CRH_IVK"),
+            cs.namespace(|| "Line 121: blake2s coin preimage CRH_IVK"),
             &preimage,
             zcash_primitives::constants::CRH_IVK_PERSONALIZATION,
         )?;
 
-        // Line 91: emit_binary coin
-        multipack::pack_into_inputs(cs.namespace(|| "Line 91: emit_binary coin"), &coin)?;
+        // Line 122: emit_binary coin
+        multipack::pack_into_inputs(cs.namespace(|| "Line 122: emit_binary coin"), &coin)?;
 
         Ok(())
     }

+ 34 - 5
src/circuit/spend_contract.rs

@@ -197,6 +197,11 @@ impl Circuit<bls12_381::Scalar> for SpendContract {
             self.randomness_coin,
         )?;
 
+        // Line 110: fr_as_binary_le asset_id param:asset_id
+        let asset_id = boolean::field_into_boolean_vec_le(
+            cs.namespace(|| "Line 109: fr_as_binary_le asset_id param:asset_id"),
+            self.randomness_coin,
+        )?;
         // Line 113: alloc_binary preimage
         let mut preimage = vec![];
 
@@ -209,9 +214,6 @@ impl Circuit<bls12_381::Scalar> for SpendContract {
         // Line 120: binary_extend preimage value
         preimage.extend(value);
 
-        // Line 121: binary_extend preimage asset_id
-        preimage.extend(asset_id);
-
         // Line 123: binary_extend preimage serial
         preimage.extend(serial);
 
@@ -266,8 +268,35 @@ impl Circuit<bls12_381::Scalar> for SpendContract {
         // Line 151: binary_push preimage zero_bit
         preimage.push(zero_bit);
 
-        // Line 159: static_assert_binary_size preimage 896
-        assert_eq!(preimage.len(), 896);
+        // Line 109: binary_extend preimage asset_id
+        preimage.extend(asset_id);
+
+        // Line 109: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 109: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 109: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 109: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 109: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 109: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 109: alloc_const_bit zero_bit false
+        let zero_bit = Boolean::constant(false);
+
+        // Line 109: binary_push preimage zero_bit
+        preimage.push(zero_bit);
+
+        // Line 159: static_assert_binary_size preimage 1088
+        assert_eq!(preimage.len(), 1088);
 
         // Line 160: blake2s coin preimage CRH_IVK
         let mut coin = blake2s::blake2s(