Sfoglia il codice sorgente

Add asset_id to coin. Unenforced for now but gets passed around and
included in the coin hash.

Nym 5 anni fa
parent
commit
9942b28e94

+ 5 - 0
proofs/mint.pism

@@ -9,6 +9,7 @@ constant CRH_IVK BlakePersonalization
 contract mint_contract
     # Value commitment
     param value U64
+    param asset_id U64
     param randomness_value Fr
 
     param serial Fr
@@ -17,6 +18,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 randomness_value param:randomness_value
     fr_as_binary_le serial param:serial
     fr_as_binary_le randomness_coin param:randomness_coin
@@ -46,6 +48,9 @@ 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) -%}

+ 5 - 0
proofs/spend.pism

@@ -11,6 +11,7 @@ constant NOTE_COMMIT PedersenPersonalization
 contract spend_contract
     # Value commitment
     param value U64
+    param asset_id U64
     param randomness_value Fr
 
     param serial Fr
@@ -24,6 +25,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 randomness_value param:randomness_value
 
     # Make value commitment
@@ -85,6 +87,9 @@ start
     # value
     binary_extend preimage value
 
+    # asset_id
+    binary_extend preimage asset_id
+
     # serial
     {{ binary_put_fr("preimage", "serial") }}
 

+ 2 - 0
src/bin/mint-classic.rs

@@ -11,6 +11,7 @@ fn main() {
     let public = jubjub::SubgroupPoint::random(&mut OsRng);
 
     let value = 110;
+    let asset_id = 1;
     let randomness_value: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
 
     let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
@@ -25,6 +26,7 @@ fn main() {
     let (proof, revealed) = create_mint_proof(
         &params,
         value,
+        asset_id,
         randomness_value,
         serial,
         randomness_coin,

+ 4 - 0
src/bin/spend-classic.rs

@@ -57,6 +57,7 @@ struct SpendRevealedValues {
 impl SpendRevealedValues {
     fn compute(
         value: u64,
+        asset_id: u64,
         randomness_value: &jubjub::Fr,
         serial: &jubjub::Fr,
         randomness_coin: &jubjub::Fr,
@@ -90,6 +91,7 @@ impl SpendRevealedValues {
                 .to_state()
                 .update(&public.to_bytes())
                 .update(&value.to_le_bytes())
+                .update(&asset_id.to_le_bytes())
                 .update(&serial.to_bytes())
                 .update(&randomness_coin.to_bytes())
                 .finalize()
@@ -170,6 +172,7 @@ fn main() {
     use rand::rngs::OsRng;
 
     let value = 110;
+    let asset_id = 1;
     let randomness_value: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
 
     let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
@@ -195,6 +198,7 @@ fn main() {
     let (proof, revealed) = create_spend_proof(
         &params,
         value,
+        asset_id,
         randomness_value,
         serial,
         randomness_coin,

+ 3 - 1
src/bin/tx.rs

@@ -158,10 +158,11 @@ fn main() {
     let builder = tx::TransactionBuilder {
         clear_inputs: vec![tx::TransactionBuilderClearInputInfo {
             value: 110,
+            asset_id: 1,
             signature_secret: cashier_secret,
         }],
         inputs: vec![],
-        outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
+        outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, asset_id: 1, public }],
     };
 
     // We will 'compile' the tx, and then serialize it to this Vec<u8>
@@ -276,6 +277,7 @@ fn main() {
         // The only constraint is that sum(value in) == sum(value out)
         outputs: vec![tx::TransactionBuilderOutputInfo {
             value: 110,
+            asset_id: 1,
             public: public2,
         }],
     };

+ 12 - 2
src/circuit/mint_contract.rs

@@ -15,6 +15,7 @@ use zcash_proofs::circuit::{ecc, pedersen_hash};
 
 pub struct MintContract {
     pub value: Option<u64>,
+    pub asset_id: Option<u64>,
     pub randomness_value: Option<jubjub::Fr>,
     pub serial: Option<jubjub::Fr>,
     pub randomness_coin: Option<jubjub::Fr>,
@@ -31,6 +32,12 @@ impl Circuit<bls12_381::Scalar> for MintContract {
             self.value,
         )?;
 
+        // Line 19: u64_as_binary_le value param:asset_id
+        let asset_id = boolean::u64_into_boolean_vec_le(
+            cs.namespace(|| "Line 19: u64_as_binary_le value param:asset_id"),
+            self.asset_id,
+        )?;
+
         // Line 19: 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"),
@@ -90,6 +97,9 @@ impl Circuit<bls12_381::Scalar> for MintContract {
         // Line 46: binary_extend preimage value
         preimage.extend(value);
 
+        // Line 47: binary_extend preimage asset_id
+        preimage.extend(asset_id);
+
         // Line 53: binary_extend preimage serial
         preimage.extend(serial);
 
@@ -112,8 +122,8 @@ impl Circuit<bls12_381::Scalar> for MintContract {
             preimage.push(zero_bit);
         }
 
-        // Line 89: static_assert_binary_size preimage 832
-        assert_eq!(preimage.len(), 832);
+        // Line 89: static_assert_binary_size preimage 896
+        assert_eq!(preimage.len(), 896);
 
         // Line 90: blake2s coin preimage CRH_IVK
         let mut coin = blake2s::blake2s(

+ 12 - 2
src/circuit/spend_contract.rs

@@ -17,6 +17,7 @@ use crate::crypto::merkle_node::SAPLING_COMMITMENT_TREE_DEPTH;
 
 pub struct SpendContract {
     pub value: Option<u64>,
+    pub asset_id: Option<u64>,
     pub randomness_value: Option<jubjub::Fr>,
     pub serial: Option<jubjub::Fr>,
     pub randomness_coin: Option<jubjub::Fr>,
@@ -36,6 +37,12 @@ impl Circuit<bls12_381::Scalar> for SpendContract {
             self.value,
         )?;
 
+        // Line 41: u64_as_binary_le value param:asset_id
+        let asset_id = boolean::u64_into_boolean_vec_le(
+            cs.namespace(|| "Line 41: u64_as_binary_le value param:value"),
+            self.asset_id,
+        )?;
+
         // Line 41: fr_as_binary_le randomness_value param:randomness_value
         let randomness_value = boolean::field_into_boolean_vec_le(
             cs.namespace(|| "Line 41: fr_as_binary_le randomness_value param:randomness_value"),
@@ -175,6 +182,9 @@ 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);
 
@@ -229,8 +239,8 @@ 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 832
-        assert_eq!(preimage.len(), 832);
+        // Line 159: static_assert_binary_size preimage 896
+        assert_eq!(preimage.len(), 896);
 
         // Line 160: blake2s coin preimage CRH_IVK
         let mut coin = blake2s::blake2s(

+ 6 - 1
src/crypto/mint_proof.rs

@@ -19,6 +19,7 @@ pub struct MintRevealedValues {
 impl MintRevealedValues {
     fn compute(
         value: u64,
+        asset_id: u64,
         randomness_value: &jubjub::Fr,
         serial: &jubjub::Fr,
         randomness_coin: &jubjub::Fr,
@@ -37,6 +38,7 @@ impl MintRevealedValues {
                 .to_state()
                 .update(&public.to_bytes())
                 .update(&value.to_le_bytes())
+                .update(&asset_id.to_le_bytes())
                 .update(&serial.to_bytes())
                 .update(&randomness_coin.to_bytes())
                 .finalize()
@@ -99,6 +101,7 @@ pub fn setup_mint_prover() -> groth16::Parameters<Bls12> {
     let params = {
         let c = MintContract {
             value: None,
+            asset_id: None,
             randomness_value: None,
             serial: None,
             randomness_coin: None,
@@ -113,16 +116,18 @@ pub fn setup_mint_prover() -> groth16::Parameters<Bls12> {
 pub fn create_mint_proof(
     params: &groth16::Parameters<Bls12>,
     value: u64,
+    asset_id: u64,
     randomness_value: jubjub::Fr,
     serial: jubjub::Fr,
     randomness_coin: jubjub::Fr,
     public: jubjub::SubgroupPoint,
 ) -> (groth16::Proof<Bls12>, MintRevealedValues) {
     let revealed =
-        MintRevealedValues::compute(value, &randomness_value, &serial, &randomness_coin, &public);
+        MintRevealedValues::compute(value, asset_id, &randomness_value, &serial, &randomness_coin, &public);
 
     let c = MintContract {
         value: Some(value),
+        asset_id: Some(asset_id),
         randomness_value: Some(randomness_value),
         serial: Some(serial),
         randomness_coin: Some(randomness_coin),

+ 6 - 0
src/crypto/note.rs

@@ -9,6 +9,7 @@ use crate::serial::{Decodable, Encodable, ReadExt, WriteExt};
 
 pub const NOTE_PLAINTEXT_SIZE: usize = 32 + // serial
     8 + // value
+    8 + // asset_id
     32 + // coin_blind
     32; // valcom_blind
 pub const AEAD_TAG_SIZE: usize = 16;
@@ -18,6 +19,7 @@ pub const ENC_CIPHERTEXT_SIZE: usize = NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE;
 pub struct Note {
     pub serial: jubjub::Fr,
     pub value: u64,
+    pub asset_id: u64,
     pub coin_blind: jubjub::Fr,
     pub valcom_blind: jubjub::Fr,
 }
@@ -27,6 +29,7 @@ impl Encodable for Note {
         let mut len = 0;
         len += self.serial.encode(&mut s)?;
         len += self.value.encode(&mut s)?;
+        len += self.asset_id.encode(&mut s)?;
         len += self.coin_blind.encode(&mut s)?;
         len += self.valcom_blind.encode(&mut s)?;
         Ok(len)
@@ -38,6 +41,7 @@ impl Decodable for Note {
         Ok(Self {
             serial: Decodable::decode(&mut d)?,
             value: Decodable::decode(&mut d)?,
+            asset_id: Decodable::decode(&mut d)?,
             coin_blind: Decodable::decode(&mut d)?,
             valcom_blind: Decodable::decode(d)?,
         })
@@ -123,6 +127,7 @@ fn test_note_encdec() {
     let note = Note {
         serial: jubjub::Fr::random(&mut OsRng),
         value: 110,
+        asset_id: 1,
         coin_blind: jubjub::Fr::random(&mut OsRng),
         valcom_blind: jubjub::Fr::random(&mut OsRng),
     };
@@ -133,4 +138,5 @@ fn test_note_encdec() {
     let encrypted_note = note.encrypt(&public).unwrap();
     let note2 = encrypted_note.decrypt(&secret).unwrap();
     assert_eq!(note.value, note2.value);
+    assert_eq!(note.asset_id, note2.asset_id);
 }

+ 6 - 0
src/crypto/spend_proof.rs

@@ -26,6 +26,7 @@ pub struct SpendRevealedValues {
 impl SpendRevealedValues {
     fn compute(
         value: u64,
+        asset_id: u64,
         randomness_value: &jubjub::Fr,
         serial: &jubjub::Fr,
         randomness_coin: &jubjub::Fr,
@@ -63,6 +64,7 @@ impl SpendRevealedValues {
                 .to_state()
                 .update(&public.to_bytes())
                 .update(&value.to_le_bytes())
+                .update(&asset_id.to_le_bytes())
                 .update(&serial.to_bytes())
                 .update(&randomness_coin.to_bytes())
                 .finalize()
@@ -180,6 +182,7 @@ pub fn setup_spend_prover() -> groth16::Parameters<Bls12> {
     let params = {
         let c = SpendContract {
             value: None,
+            asset_id: None,
             randomness_value: None,
             serial: None,
             randomness_coin: None,
@@ -199,6 +202,7 @@ pub fn setup_spend_prover() -> groth16::Parameters<Bls12> {
 pub fn create_spend_proof(
     params: &groth16::Parameters<Bls12>,
     value: u64,
+    asset_id: u64,
     randomness_value: jubjub::Fr,
     serial: jubjub::Fr,
     randomness_coin: jubjub::Fr,
@@ -215,6 +219,7 @@ pub fn create_spend_proof(
     }
     let c = SpendContract {
         value: Some(value),
+        asset_id: Some(asset_id),
         randomness_value: Some(randomness_value),
         serial: Some(serial),
         randomness_coin: Some(randomness_coin),
@@ -232,6 +237,7 @@ pub fn create_spend_proof(
 
     let revealed = SpendRevealedValues::compute(
         value,
+        asset_id,
         &randomness_value,
         &serial,
         &randomness_coin,

+ 6 - 0
src/tx/builder.rs

@@ -21,6 +21,7 @@ pub struct TransactionBuilder {
 
 pub struct TransactionBuilderClearInputInfo {
     pub value: u64,
+    pub asset_id: u64,
     pub signature_secret: jubjub::Fr,
 }
 
@@ -32,6 +33,7 @@ pub struct TransactionBuilderInputInfo {
 
 pub struct TransactionBuilderOutputInfo {
     pub value: u64,
+    pub asset_id: u64,
     pub public: jubjub::SubgroupPoint,
 }
 
@@ -71,6 +73,7 @@ impl TransactionBuilder {
             let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
             let clear_input = PartialTransactionClearInput {
                 value: input.value,
+                asset_id: input.asset_id,
                 valcom_blind,
                 signature_public,
             };
@@ -98,6 +101,7 @@ impl TransactionBuilder {
             let (proof, revealed) = create_spend_proof(
                 &spend_params,
                 input.note.value,
+                input.note.asset_id,
                 input.note.valcom_blind,
                 input.note.serial,
                 input.note.coin_blind,
@@ -133,6 +137,7 @@ impl TransactionBuilder {
             let (mint_proof, revealed) = create_mint_proof(
                 mint_params,
                 output.value,
+                output.asset_id,
                 valcom_blind.clone(),
                 serial.clone(),
                 coin_blind.clone(),
@@ -144,6 +149,7 @@ impl TransactionBuilder {
             let note = Note {
                 serial,
                 value: output.value,
+                asset_id: output.asset_id,
                 coin_blind,
                 valcom_blind,
             };

+ 5 - 0
src/tx/mod.rs

@@ -29,6 +29,7 @@ pub struct Transaction {
 
 pub struct TransactionClearInput {
     pub value: u64,
+    pub asset_id: u64,
     pub valcom_blind: jubjub::Fr,
     pub signature_public: jubjub::SubgroupPoint,
     pub signature: schnorr::Signature,
@@ -113,6 +114,7 @@ impl TransactionClearInput {
     fn from_partial(partial: PartialTransactionClearInput, signature: schnorr::Signature) -> Self {
         Self {
             value: partial.value,
+            asset_id: partial.asset_id,
             valcom_blind: partial.valcom_blind,
             signature_public: partial.signature_public,
             signature,
@@ -122,6 +124,7 @@ impl TransactionClearInput {
     fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.value.encode(&mut s)?;
+        len += self.asset_id.encode(&mut s)?;
         len += self.valcom_blind.encode(&mut s)?;
         len += self.signature_public.encode(s)?;
         Ok(len)
@@ -169,6 +172,7 @@ impl Encodable for TransactionClearInput {
     fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.value.encode(&mut s)?;
+        len += self.asset_id.encode(&mut s)?;
         len += self.valcom_blind.encode(&mut s)?;
         len += self.signature_public.encode(&mut s)?;
         len += self.signature.encode(s)?;
@@ -180,6 +184,7 @@ impl Decodable for TransactionClearInput {
     fn decode<D: io::Read>(mut d: D) -> Result<Self> {
         Ok(Self {
             value: Decodable::decode(&mut d)?,
+            asset_id: Decodable::decode(&mut d)?,
             valcom_blind: Decodable::decode(&mut d)?,
             signature_public: Decodable::decode(&mut d)?,
             signature: Decodable::decode(d)?,

+ 3 - 0
src/tx/partial.rs

@@ -16,6 +16,7 @@ pub struct PartialTransaction {
 
 pub struct PartialTransactionClearInput {
     pub value: u64,
+    pub asset_id: u64,
     pub valcom_blind: jubjub::Fr,
     pub signature_public: jubjub::SubgroupPoint,
 }
@@ -49,6 +50,7 @@ impl Encodable for PartialTransactionClearInput {
     fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         len += self.value.encode(&mut s)?;
+        len += self.asset_id.encode(&mut s)?;
         len += self.valcom_blind.encode(&mut s)?;
         len += self.signature_public.encode(&mut s)?;
         Ok(len)
@@ -58,6 +60,7 @@ impl Decodable for PartialTransactionClearInput {
     fn decode<D: io::Read>(mut d: D) -> Result<Self> {
         Ok(Self {
             value: Decodable::decode(&mut d)?,
+            asset_id: Decodable::decode(&mut d)?,
             valcom_blind: Decodable::decode(&mut d)?,
             signature_public: Decodable::decode(&mut d)?,
         })