Browse Source

add clear_outputs field to txs

narodnik 5 năm trước cách đây
mục cha
commit
d904dcdc46
2 tập tin đã thay đổi với 83 bổ sung7 xóa
  1. 4 0
      src/bin/tx.rs
  2. 79 7
      src/tx.rs

+ 4 - 0
src/bin/tx.rs

@@ -51,6 +51,7 @@ fn main() {
         clear_inputs: vec![tx::TransactionBuilderClearInputInfo { value: 110, signature_secret: cashier_secret }],
         inputs: vec![],
         outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
+        clear_outputs: vec![]
     };
 
     // We will 'compile' the tx, and then serialize it to this Vec<u8>
@@ -159,6 +160,7 @@ fn main() {
         // We can add more outputs to this list.
         // The only constraint is that sum(value in) == sum(value out)
         outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public: public2 }],
+        clear_outputs: vec![]
     };
     // Build the tx
     let mut tx_data = vec![];
@@ -171,5 +173,7 @@ fn main() {
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
         assert!(tx.verify(&mint_pvk, &spend_pvk));
     }
+
+    // Step 4 withdraw the funds
 }
 

+ 79 - 7
src/tx.rs

@@ -22,6 +22,7 @@ pub struct TransactionBuilder {
     pub clear_inputs: Vec<TransactionBuilderClearInputInfo>,
     pub inputs: Vec<TransactionBuilderInputInfo>,
     pub outputs: Vec<TransactionBuilderOutputInfo>,
+    pub clear_outputs: Vec<TransactionBuilderClearOutputInfo>,
 }
 
 impl TransactionBuilder {
@@ -29,6 +30,7 @@ impl TransactionBuilder {
         clear_inputs: &Vec<PartialTransactionClearInput>,
         input_blinds: &Vec<jubjub::Fr>,
         output_blinds: &Vec<jubjub::Fr>,
+        clear_outputs: &Vec<TransactionClearOutput>,
     ) -> jubjub::Fr {
         let mut total = jubjub::Fr::zero();
 
@@ -44,6 +46,10 @@ impl TransactionBuilder {
             total -= output_blind;
         }
 
+        for output in clear_outputs {
+            total -= output.valcom_blind;
+        }
+
         total
     }
 
@@ -98,11 +104,13 @@ impl TransactionBuilder {
             inputs.push(input);
         }
 
+        let last_output_index = self.outputs.len() + self.clear_outputs.len() - 1;
+
         let mut outputs = vec![];
         let mut output_blinds = vec![];
         for (i, output) in self.outputs.iter().enumerate() {
-            let valcom_blind = if i == self.outputs.len() - 1 {
-                Self::compute_remainder_blind(&clear_inputs, &input_blinds, &output_blinds)
+            let valcom_blind = if i == last_output_index {
+                Self::compute_remainder_blind(&clear_inputs, &input_blinds, &output_blinds, &vec![])
             } else {
                 jubjub::Fr::random(&mut OsRng)
             };
@@ -139,10 +147,28 @@ impl TransactionBuilder {
             outputs.push(output);
         }
 
+        let mut clear_outputs = vec![];
+
+        for (i, output) in self.clear_outputs.into_iter().enumerate() {
+            let valcom_blind = if self.outputs.len() + i == last_output_index {
+                Self::compute_remainder_blind(&clear_inputs, &input_blinds, &output_blinds, &clear_outputs)
+            } else {
+                jubjub::Fr::random(&mut OsRng)
+            };
+
+            let output = TransactionClearOutput {
+                value: output.value,
+                valcom_blind,
+                instructions: output.instructions
+            };
+            clear_outputs.push(output);
+        }
+
         let partial_tx = PartialTransaction {
             clear_inputs,
             inputs,
             outputs,
+            clear_outputs
         };
 
         let mut unsigned_tx_data = vec![];
@@ -173,10 +199,16 @@ impl TransactionBuilder {
             clear_inputs,
             inputs,
             outputs: partial_tx.outputs,
+            clear_outputs: partial_tx.clear_outputs
         }
     }
 }
 
+pub struct TransactionBuilderClearOutputInfo {
+    pub value: u64,
+    pub instructions: String
+}
+
 pub struct TransactionBuilderClearInputInfo {
     pub value: u64,
     pub signature_secret: jubjub::Fr,
@@ -199,6 +231,7 @@ pub struct PartialTransaction {
     pub clear_inputs: Vec<PartialTransactionClearInput>,
     pub inputs: Vec<PartialTransactionInput>,
     pub outputs: Vec<TransactionOutput>,
+    pub clear_outputs: Vec<TransactionClearOutput>,
 }
 
 impl Encodable for PartialTransaction {
@@ -206,7 +239,8 @@ impl Encodable for PartialTransaction {
         let mut len = 0;
         len += self.clear_inputs.encode(&mut s)?;
         len += self.inputs.encode(&mut s)?;
-        len += self.outputs.encode(s)?;
+        len += self.outputs.encode(&mut s)?;
+        len += self.clear_outputs.encode(&mut s)?;
         Ok(len)
     }
 }
@@ -216,7 +250,8 @@ impl Decodable for PartialTransaction {
         Ok(Self {
             clear_inputs: Decodable::decode(&mut d)?,
             inputs: Decodable::decode(&mut d)?,
-            outputs: Decodable::decode(d)?,
+            outputs: Decodable::decode(&mut d)?,
+            clear_outputs: Decodable::decode(&mut d)?,
         })
     }
 }
@@ -225,6 +260,7 @@ pub struct Transaction {
     pub clear_inputs: Vec<TransactionClearInput>,
     pub inputs: Vec<TransactionInput>,
     pub outputs: Vec<TransactionOutput>,
+    pub clear_outputs: Vec<TransactionClearOutput>
 }
 
 impl Encodable for Transaction {
@@ -232,7 +268,8 @@ impl Encodable for Transaction {
         let mut len = 0;
         len += self.clear_inputs.encode(&mut s)?;
         len += self.inputs.encode(&mut s)?;
-        len += self.outputs.encode(s)?;
+        len += self.outputs.encode(&mut s)?;
+        len += self.clear_outputs.encode(&mut s)?;
         Ok(len)
     }
 }
@@ -242,7 +279,8 @@ impl Decodable for Transaction {
         Ok(Self {
             clear_inputs: Decodable::decode(&mut d)?,
             inputs: Decodable::decode(&mut d)?,
-            outputs: Decodable::decode(d)?,
+            outputs: Decodable::decode(&mut d)?,
+            clear_outputs: Decodable::decode(&mut d)?,
         })
     }
 }
@@ -252,7 +290,8 @@ impl Transaction {
         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)?;
+        len += self.outputs.encode(&mut s)?;
+        len += self.clear_outputs.encode(&mut s)?;
         Ok(len)
     }
 
@@ -274,6 +313,7 @@ impl Transaction {
         }
         for input in &self.inputs {
             if !verify_spend_proof(spend_pvk, &input.spend_proof, &input.revealed) {
+                println!("spend fail");
                 return false;
             }
             valcom_total += &input.revealed.value_commit;
@@ -285,6 +325,9 @@ impl Transaction {
             }
             valcom_total -= &output.revealed.value_commit;
         }
+        for output in &self.clear_outputs {
+            valcom_total -= Self::compute_value_commit(output.value, &output.valcom_blind);
+        }
 
         // Verify signatures
         let mut unsigned_tx_data = vec![];
@@ -507,3 +550,32 @@ impl Decodable for TransactionOutput {
         })
     }
 }
+
+pub struct TransactionClearOutput {
+    pub value: u64,
+    pub valcom_blind: jubjub::Fr,
+    pub instructions: String
+}
+
+impl_vec!(TransactionClearOutput);
+
+impl Encodable for TransactionClearOutput {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.value.encode(&mut s)?;
+        len += self.valcom_blind.encode(&mut s)?;
+        len += self.instructions.encode(s)?;
+        Ok(len)
+    }
+}
+
+impl Decodable for TransactionClearOutput {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        Ok(Self {
+            value: Decodable::decode(&mut d)?,
+            valcom_blind: Decodable::decode(&mut d)?,
+            instructions: Decodable::decode(&mut d)?,
+        })
+    }
+}
+