Просмотр исходного кода

daod: created money_contract/transfer subdir

lunar-mining 4 лет назад
Родитель
Сommit
7263e8eb6b

+ 8 - 221
bin/daod/src/money_contract/mod.rs

@@ -1,3 +1,10 @@
+// TODO
+// money-contract/
+// state.apply()
+//      transfer/
+//          Builder
+//          Partial *
+//          FuncCall
 use std::io;
 
 use log::error;
@@ -20,224 +27,4 @@ use darkfi::{
     Result, VerifyFailed, VerifyResult,
 };
 
-pub mod builder;
-pub mod partial;
-
-/// A DarkFi transaction
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct Transaction {
-    /// Clear inputs
-    pub clear_inputs: Vec<TransactionClearInput>,
-    /// Anonymous inputs
-    pub inputs: Vec<TransactionInput>,
-    /// Anonymous outputs
-    pub outputs: Vec<TransactionOutput>,
-}
-
-/// A transaction's clear input
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct TransactionClearInput {
-    /// Input's value (amount)
-    pub value: u64,
-    /// Input's token ID
-    pub token_id: DrkTokenId,
-    /// Blinding factor for `value`
-    pub value_blind: DrkValueBlind,
-    /// Blinding factor for `token_id`
-    pub token_blind: DrkValueBlind,
-    /// Public key for the signature
-    pub signature_public: PublicKey,
-    /// Transaction signature
-    pub signature: schnorr::Signature,
-}
-
-/// A transaction's anonymous input
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct TransactionInput {
-    /// Zero-knowledge proof for the input
-    pub burn_proof: Proof,
-    /// Public inputs for the zero-knowledge proof
-    pub revealed: BurnRevealedValues,
-    /// Input's signature
-    pub signature: schnorr::Signature,
-}
-
-/// A transaction's anonymous output
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct TransactionOutput {
-    /// Zero-knowledge proof for the output
-    pub mint_proof: Proof,
-    /// Public inputs for the zero-knowledge proof
-    pub revealed: MintRevealedValues,
-    /// The encrypted note
-    pub enc_note: EncryptedNote,
-}
-
-impl Transaction {
-    /// Verify the transaction
-    pub fn verify(&self, mint_vk: &VerifyingKey, burn_vk: &VerifyingKey) -> VerifyResult<()> {
-        // Transaction must have minimum 1 clear or anon input, and 1 output
-        if self.clear_inputs.len() + self.inputs.len() == 0 {
-            error!("tx::verify(): Missing inputs");
-            return Err(VerifyFailed::LackingInputs)
-        }
-        if self.outputs.len() == 0 {
-            error!("tx::verify(): Missing outputs");
-            return Err(VerifyFailed::LackingOutputs)
-        }
-
-        // Accumulator for the value commitments
-        let mut valcom_total = DrkValueCommit::identity();
-
-        // Add values from the clear inputs
-        for input in &self.clear_inputs {
-            valcom_total += pedersen_commitment_u64(input.value, input.value_blind);
-        }
-
-        // Add values from the inputs
-        for (i, input) in self.inputs.iter().enumerate() {
-            match verify_burn_proof(burn_vk, &input.burn_proof, &input.revealed) {
-                Ok(()) => valcom_total += &input.revealed.value_commit,
-                Err(e) => {
-                    error!("tx::verify(): Failed to verify burn proof {}: {}", i, e);
-                    return Err(VerifyFailed::BurnProof(i))
-                }
-            }
-        }
-
-        // Subtract values from the outputs
-        for (i, output) in self.outputs.iter().enumerate() {
-            match verify_mint_proof(mint_vk, &output.mint_proof, &output.revealed) {
-                Ok(()) => valcom_total -= &output.revealed.value_commit,
-                Err(e) => {
-                    error!("tx::verify(): Failed to verify mint proof {}: {}", i, e);
-                    return Err(VerifyFailed::MintProof(i))
-                }
-            }
-        }
-
-        // If the accumulator is not back in its initial state,
-        // there's a value mismatch.
-        if valcom_total != DrkValueCommit::identity() {
-            error!("tx::verify(): Missing funds");
-            return Err(VerifyFailed::MissingFunds)
-        }
-
-        // Verify that the token commitments match
-        if !self.verify_token_commitments() {
-            error!("tx::verify(): Token ID mismatch");
-            return Err(VerifyFailed::TokenMismatch)
-        }
-
-        // Verify the available signatures
-        let mut unsigned_tx_data = vec![];
-        self.encode_without_signature(&mut unsigned_tx_data)?;
-
-        for (i, input) in self.clear_inputs.iter().enumerate() {
-            let public = &input.signature_public;
-            if !public.verify(&unsigned_tx_data[..], &input.signature) {
-                error!("tx::verify(): Failed to verify Clear Input signature {}", i);
-                return Err(VerifyFailed::ClearInputSignature(i))
-            }
-        }
-
-        for (i, input) in self.inputs.iter().enumerate() {
-            let public = &input.revealed.signature_public;
-            if !public.verify(&unsigned_tx_data[..], &input.signature) {
-                error!("tx::verify(): Failed to verify Input signature {}", i);
-                return Err(VerifyFailed::InputSignature(i))
-            }
-        }
-
-        Ok(())
-    }
-
-    pub fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
-        let mut len = 0;
-        len += self.clear_inputs.encode_without_signature(&mut s)?;
-        len += self.inputs.encode_without_signature(&mut s)?;
-        len += self.outputs.encode(s)?;
-        Ok(len)
-    }
-
-    fn verify_token_commitments(&self) -> bool {
-        assert_ne!(self.outputs.len(), 0);
-        let token_commit_value = self.outputs[0].revealed.token_commit;
-
-        let mut failed =
-            self.inputs.iter().any(|input| input.revealed.token_commit != token_commit_value);
-
-        failed = failed ||
-            self.outputs.iter().any(|output| output.revealed.token_commit != token_commit_value);
-
-        failed = failed ||
-            self.clear_inputs.iter().any(|input| {
-                pedersen_commitment_base(input.token_id, input.token_blind) != token_commit_value
-            });
-        !failed
-    }
-}
-
-impl TransactionClearInput {
-    fn from_partial(
-        partial: partial::PartialTransactionClearInput,
-        signature: schnorr::Signature,
-    ) -> Self {
-        Self {
-            value: partial.value,
-            token_id: partial.token_id,
-            value_blind: partial.value_blind,
-            token_blind: partial.token_blind,
-            signature_public: partial.signature_public,
-            signature,
-        }
-    }
-
-    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.token_id.encode(&mut s)?;
-        len += self.value_blind.encode(&mut s)?;
-        len += self.token_blind.encode(&mut s)?;
-        len += self.signature_public.encode(s)?;
-        Ok(len)
-    }
-}
-
-impl TransactionInput {
-    pub fn from_partial(
-        partial: partial::PartialTransactionInput,
-        signature: schnorr::Signature,
-    ) -> Self {
-        Self { burn_proof: partial.burn_proof, revealed: partial.revealed, signature }
-    }
-
-    fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
-        let mut len = 0;
-        len += self.burn_proof.encode(&mut s)?;
-        len += self.revealed.encode(&mut s)?;
-        Ok(len)
-    }
-}
-
-trait EncodableWithoutSignature {
-    fn encode_without_signature<S: io::Write>(&self, s: S) -> Result<usize>;
-}
-
-macro_rules! impl_vec_without_signature {
-    ($type: ty) => {
-        impl EncodableWithoutSignature for Vec<$type> {
-            #[inline]
-            fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
-                let mut len = 0;
-                len += VarInt(self.len() as u64).encode(&mut s)?;
-                for c in self.iter() {
-                    len += c.encode_without_signature(&mut s)?;
-                }
-                Ok(len)
-            }
-        }
-    };
-}
-impl_vec_without_signature!(TransactionClearInput);
-impl_vec_without_signature!(TransactionInput);
+pub mod transfer;

+ 1 - 0
bin/daod/src/money_contract/builder.rs → bin/daod/src/money_contract/transfer/builder.rs

@@ -5,6 +5,7 @@ use super::{
     partial::{PartialTransaction, PartialTransactionClearInput, PartialTransactionInput},
     Transaction, TransactionClearInput, TransactionInput, TransactionOutput,
 };
+
 use darkfi::{
     crypto::{
         burn_proof::create_burn_proof,

+ 243 - 0
bin/daod/src/money_contract/transfer/mod.rs

@@ -0,0 +1,243 @@
+use std::io;
+
+use log::error;
+use pasta_curves::group::Group;
+
+use darkfi::{
+    crypto::{
+        burn_proof::verify_burn_proof,
+        keypair::PublicKey,
+        mint_proof::verify_mint_proof,
+        note::EncryptedNote,
+        proof::VerifyingKey,
+        schnorr,
+        schnorr::SchnorrPublic,
+        types::{DrkTokenId, DrkValueBlind, DrkValueCommit},
+        util::{pedersen_commitment_base, pedersen_commitment_u64},
+        BurnRevealedValues, MintRevealedValues, Proof,
+    },
+    util::serial::{Encodable, SerialDecodable, SerialEncodable, VarInt},
+    Result, VerifyFailed, VerifyResult,
+};
+
+pub mod builder;
+pub mod partial;
+
+/// A DarkFi transaction
+#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
+pub struct Transaction {
+    /// Clear inputs
+    pub clear_inputs: Vec<TransactionClearInput>,
+    /// Anonymous inputs
+    pub inputs: Vec<TransactionInput>,
+    /// Anonymous outputs
+    pub outputs: Vec<TransactionOutput>,
+}
+
+/// A transaction's clear input
+#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
+pub struct TransactionClearInput {
+    /// Input's value (amount)
+    pub value: u64,
+    /// Input's token ID
+    pub token_id: DrkTokenId,
+    /// Blinding factor for `value`
+    pub value_blind: DrkValueBlind,
+    /// Blinding factor for `token_id`
+    pub token_blind: DrkValueBlind,
+    /// Public key for the signature
+    pub signature_public: PublicKey,
+    /// Transaction signature
+    pub signature: schnorr::Signature,
+}
+
+/// A transaction's anonymous input
+#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
+pub struct TransactionInput {
+    /// Zero-knowledge proof for the input
+    pub burn_proof: Proof,
+    /// Public inputs for the zero-knowledge proof
+    pub revealed: BurnRevealedValues,
+    /// Input's signature
+    pub signature: schnorr::Signature,
+}
+
+/// A transaction's anonymous output
+#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
+pub struct TransactionOutput {
+    /// Zero-knowledge proof for the output
+    pub mint_proof: Proof,
+    /// Public inputs for the zero-knowledge proof
+    pub revealed: MintRevealedValues,
+    /// The encrypted note
+    pub enc_note: EncryptedNote,
+}
+
+impl Transaction {
+    /// Verify the transaction
+    pub fn verify(&self, mint_vk: &VerifyingKey, burn_vk: &VerifyingKey) -> VerifyResult<()> {
+        // Transaction must have minimum 1 clear or anon input, and 1 output
+        if self.clear_inputs.len() + self.inputs.len() == 0 {
+            error!("tx::verify(): Missing inputs");
+            return Err(VerifyFailed::LackingInputs)
+        }
+        if self.outputs.len() == 0 {
+            error!("tx::verify(): Missing outputs");
+            return Err(VerifyFailed::LackingOutputs)
+        }
+
+        // Accumulator for the value commitments
+        let mut valcom_total = DrkValueCommit::identity();
+
+        // Add values from the clear inputs
+        for input in &self.clear_inputs {
+            valcom_total += pedersen_commitment_u64(input.value, input.value_blind);
+        }
+
+        // Add values from the inputs
+        for (i, input) in self.inputs.iter().enumerate() {
+            match verify_burn_proof(burn_vk, &input.burn_proof, &input.revealed) {
+                Ok(()) => valcom_total += &input.revealed.value_commit,
+                Err(e) => {
+                    error!("tx::verify(): Failed to verify burn proof {}: {}", i, e);
+                    return Err(VerifyFailed::BurnProof(i))
+                }
+            }
+        }
+
+        // Subtract values from the outputs
+        for (i, output) in self.outputs.iter().enumerate() {
+            match verify_mint_proof(mint_vk, &output.mint_proof, &output.revealed) {
+                Ok(()) => valcom_total -= &output.revealed.value_commit,
+                Err(e) => {
+                    error!("tx::verify(): Failed to verify mint proof {}: {}", i, e);
+                    return Err(VerifyFailed::MintProof(i))
+                }
+            }
+        }
+
+        // If the accumulator is not back in its initial state,
+        // there's a value mismatch.
+        if valcom_total != DrkValueCommit::identity() {
+            error!("tx::verify(): Missing funds");
+            return Err(VerifyFailed::MissingFunds)
+        }
+
+        // Verify that the token commitments match
+        if !self.verify_token_commitments() {
+            error!("tx::verify(): Token ID mismatch");
+            return Err(VerifyFailed::TokenMismatch)
+        }
+
+        // Verify the available signatures
+        let mut unsigned_tx_data = vec![];
+        self.encode_without_signature(&mut unsigned_tx_data)?;
+
+        for (i, input) in self.clear_inputs.iter().enumerate() {
+            let public = &input.signature_public;
+            if !public.verify(&unsigned_tx_data[..], &input.signature) {
+                error!("tx::verify(): Failed to verify Clear Input signature {}", i);
+                return Err(VerifyFailed::ClearInputSignature(i))
+            }
+        }
+
+        for (i, input) in self.inputs.iter().enumerate() {
+            let public = &input.revealed.signature_public;
+            if !public.verify(&unsigned_tx_data[..], &input.signature) {
+                error!("tx::verify(): Failed to verify Input signature {}", i);
+                return Err(VerifyFailed::InputSignature(i))
+            }
+        }
+
+        Ok(())
+    }
+
+    pub fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.clear_inputs.encode_without_signature(&mut s)?;
+        len += self.inputs.encode_without_signature(&mut s)?;
+        len += self.outputs.encode(s)?;
+        Ok(len)
+    }
+
+    fn verify_token_commitments(&self) -> bool {
+        assert_ne!(self.outputs.len(), 0);
+        let token_commit_value = self.outputs[0].revealed.token_commit;
+
+        let mut failed =
+            self.inputs.iter().any(|input| input.revealed.token_commit != token_commit_value);
+
+        failed = failed ||
+            self.outputs.iter().any(|output| output.revealed.token_commit != token_commit_value);
+
+        failed = failed ||
+            self.clear_inputs.iter().any(|input| {
+                pedersen_commitment_base(input.token_id, input.token_blind) != token_commit_value
+            });
+        !failed
+    }
+}
+
+impl TransactionClearInput {
+    fn from_partial(
+        partial: partial::PartialTransactionClearInput,
+        signature: schnorr::Signature,
+    ) -> Self {
+        Self {
+            value: partial.value,
+            token_id: partial.token_id,
+            value_blind: partial.value_blind,
+            token_blind: partial.token_blind,
+            signature_public: partial.signature_public,
+            signature,
+        }
+    }
+
+    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.token_id.encode(&mut s)?;
+        len += self.value_blind.encode(&mut s)?;
+        len += self.token_blind.encode(&mut s)?;
+        len += self.signature_public.encode(s)?;
+        Ok(len)
+    }
+}
+
+impl TransactionInput {
+    pub fn from_partial(
+        partial: partial::PartialTransactionInput,
+        signature: schnorr::Signature,
+    ) -> Self {
+        Self { burn_proof: partial.burn_proof, revealed: partial.revealed, signature }
+    }
+
+    fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.burn_proof.encode(&mut s)?;
+        len += self.revealed.encode(&mut s)?;
+        Ok(len)
+    }
+}
+
+trait EncodableWithoutSignature {
+    fn encode_without_signature<S: io::Write>(&self, s: S) -> Result<usize>;
+}
+
+macro_rules! impl_vec_without_signature {
+    ($type: ty) => {
+        impl EncodableWithoutSignature for Vec<$type> {
+            #[inline]
+            fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
+                let mut len = 0;
+                len += VarInt(self.len() as u64).encode(&mut s)?;
+                for c in self.iter() {
+                    len += c.encode_without_signature(&mut s)?;
+                }
+                Ok(len)
+            }
+        }
+    };
+}
+impl_vec_without_signature!(TransactionClearInput);
+impl_vec_without_signature!(TransactionInput);

+ 0 - 0
bin/daod/src/money_contract/partial.rs → bin/daod/src/money_contract/transfer/partial.rs