add clear_outputs field to txs

This commit is contained in:
narodnik
2021-05-15 10:01:16 +02:00
parent d84a84fc65
commit d904dcdc46
2 changed files with 83 additions and 7 deletions

View File

@@ -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
}

View File

@@ -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)?,
})
}
}