tx.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. use bellman::groth16;
  2. use bls12_381::Bls12;
  3. use ff::Field;
  4. use group::Group;
  5. use rand::rngs::OsRng;
  6. use std::collections::HashMap;
  7. use std::io;
  8. use crate::crypto::{
  9. coin::Coin,
  10. create_mint_proof, create_spend_proof, load_params,
  11. merkle::CommitmentTree,
  12. note::{EncryptedNote, Note},
  13. save_params, schnorr, setup_mint_prover, setup_spend_prover, verify_mint_proof,
  14. verify_spend_proof, MintRevealedValues, SpendRevealedValues,
  15. };
  16. use crate::error::{Error, Result};
  17. use crate::impl_vec;
  18. use crate::serial::{Decodable, Encodable, VarInt};
  19. pub struct TransactionBuilder {
  20. pub clear_inputs: Vec<TransactionBuilderClearInputInfo>,
  21. pub inputs: Vec<TransactionBuilderInputInfo>,
  22. pub outputs: Vec<TransactionBuilderOutputInfo>,
  23. pub clear_outputs: Vec<TransactionBuilderClearOutputInfo>,
  24. }
  25. impl TransactionBuilder {
  26. fn compute_remainder_blind(
  27. clear_inputs: &Vec<PartialTransactionClearInput>,
  28. input_blinds: &Vec<jubjub::Fr>,
  29. output_blinds: &Vec<jubjub::Fr>,
  30. clear_outputs: &Vec<TransactionClearOutput>,
  31. ) -> jubjub::Fr {
  32. let mut total = jubjub::Fr::zero();
  33. for input in clear_inputs {
  34. total += input.valcom_blind;
  35. }
  36. for input_blind in input_blinds {
  37. total += input_blind;
  38. }
  39. for output_blind in output_blinds {
  40. total -= output_blind;
  41. }
  42. for output in clear_outputs {
  43. total -= output.valcom_blind;
  44. }
  45. total
  46. }
  47. pub fn build(
  48. self,
  49. mint_params: &groth16::Parameters<Bls12>,
  50. spend_params: &groth16::Parameters<Bls12>,
  51. ) -> Transaction {
  52. let mut clear_inputs = vec![];
  53. for input in &self.clear_inputs {
  54. let signature_public =
  55. zcash_primitives::constants::SPENDING_KEY_GENERATOR * input.signature_secret;
  56. let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  57. let clear_input = PartialTransactionClearInput {
  58. value: input.value,
  59. valcom_blind,
  60. signature_public,
  61. };
  62. clear_inputs.push(clear_input);
  63. }
  64. let mut inputs = vec![];
  65. let mut input_blinds = vec![];
  66. let mut signature_secrets = vec![];
  67. for input in &self.inputs {
  68. input_blinds.push(input.note.valcom_blind.clone());
  69. let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  70. // make proof
  71. let (proof, revealed) = create_spend_proof(
  72. &spend_params,
  73. input.note.value,
  74. input.note.valcom_blind,
  75. input.note.serial,
  76. input.note.coin_blind,
  77. input.secret,
  78. input.merkle_path.clone(),
  79. signature_secret.clone(),
  80. );
  81. // First we make the tx then sign after
  82. let signature_secret = schnorr::SecretKey(signature_secret);
  83. signature_secrets.push(signature_secret);
  84. let input = PartialTransactionInput {
  85. spend_proof: proof,
  86. revealed,
  87. };
  88. inputs.push(input);
  89. }
  90. let last_output_index = self.outputs.len() + self.clear_outputs.len() - 1;
  91. let mut outputs = vec![];
  92. let mut output_blinds = vec![];
  93. for (i, output) in self.outputs.iter().enumerate() {
  94. let valcom_blind = if i == last_output_index {
  95. Self::compute_remainder_blind(&clear_inputs, &input_blinds, &output_blinds, &vec![])
  96. } else {
  97. jubjub::Fr::random(&mut OsRng)
  98. };
  99. output_blinds.push(valcom_blind);
  100. let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  101. let coin_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
  102. let (mint_proof, revealed) = create_mint_proof(
  103. mint_params,
  104. output.value,
  105. valcom_blind.clone(),
  106. serial.clone(),
  107. coin_blind.clone(),
  108. output.public.clone(),
  109. );
  110. // Encrypted note
  111. let note = Note {
  112. serial,
  113. value: output.value,
  114. coin_blind,
  115. valcom_blind,
  116. };
  117. let encrypted_note = note.encrypt(&output.public).unwrap();
  118. let output = TransactionOutput {
  119. mint_proof,
  120. revealed,
  121. enc_note: encrypted_note,
  122. };
  123. outputs.push(output);
  124. }
  125. let mut clear_outputs = vec![];
  126. for (i, output) in self.clear_outputs.into_iter().enumerate() {
  127. let valcom_blind = if self.outputs.len() + i == last_output_index {
  128. Self::compute_remainder_blind(
  129. &clear_inputs,
  130. &input_blinds,
  131. &output_blinds,
  132. &clear_outputs,
  133. )
  134. } else {
  135. jubjub::Fr::random(&mut OsRng)
  136. };
  137. let output = TransactionClearOutput {
  138. value: output.value,
  139. valcom_blind,
  140. instructions: output.instructions,
  141. };
  142. clear_outputs.push(output);
  143. }
  144. let partial_tx = PartialTransaction {
  145. clear_inputs,
  146. inputs,
  147. outputs,
  148. clear_outputs,
  149. };
  150. let mut unsigned_tx_data = vec![];
  151. partial_tx
  152. .encode(&mut unsigned_tx_data)
  153. .expect("TODO handle this");
  154. let mut clear_inputs = vec![];
  155. for (input, info) in partial_tx.clear_inputs.into_iter().zip(self.clear_inputs) {
  156. let secret = schnorr::SecretKey(info.signature_secret.clone());
  157. let signature = secret.sign(&unsigned_tx_data[..]);
  158. let input = TransactionClearInput::from_partial(input, signature);
  159. clear_inputs.push(input);
  160. }
  161. let mut inputs = vec![];
  162. for (input, signature_secret) in partial_tx
  163. .inputs
  164. .into_iter()
  165. .zip(signature_secrets.into_iter())
  166. {
  167. let signature = signature_secret.sign(&unsigned_tx_data[..]);
  168. let input = TransactionInput::from_partial(input, signature);
  169. inputs.push(input);
  170. }
  171. Transaction {
  172. clear_inputs,
  173. inputs,
  174. outputs: partial_tx.outputs,
  175. clear_outputs: partial_tx.clear_outputs,
  176. }
  177. }
  178. }
  179. pub struct TransactionBuilderClearOutputInfo {
  180. pub value: u64,
  181. pub instructions: String,
  182. }
  183. pub struct TransactionBuilderClearInputInfo {
  184. pub value: u64,
  185. pub signature_secret: jubjub::Fr,
  186. }
  187. pub struct TransactionBuilderInputInfo {
  188. pub coin: [u8; 32],
  189. pub merkle_path: Vec<(bls12_381::Scalar, bool)>,
  190. pub merkle_root: CommitmentTree<Coin>,
  191. pub secret: jubjub::Fr,
  192. pub note: Note,
  193. }
  194. pub struct TransactionBuilderOutputInfo {
  195. pub value: u64,
  196. pub public: jubjub::SubgroupPoint,
  197. }
  198. pub struct PartialTransaction {
  199. pub clear_inputs: Vec<PartialTransactionClearInput>,
  200. pub inputs: Vec<PartialTransactionInput>,
  201. pub outputs: Vec<TransactionOutput>,
  202. pub clear_outputs: Vec<TransactionClearOutput>,
  203. }
  204. impl Encodable for PartialTransaction {
  205. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  206. let mut len = 0;
  207. len += self.clear_inputs.encode(&mut s)?;
  208. len += self.inputs.encode(&mut s)?;
  209. len += self.outputs.encode(&mut s)?;
  210. len += self.clear_outputs.encode(&mut s)?;
  211. Ok(len)
  212. }
  213. }
  214. impl Decodable for PartialTransaction {
  215. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  216. Ok(Self {
  217. clear_inputs: Decodable::decode(&mut d)?,
  218. inputs: Decodable::decode(&mut d)?,
  219. outputs: Decodable::decode(&mut d)?,
  220. clear_outputs: Decodable::decode(&mut d)?,
  221. })
  222. }
  223. }
  224. pub struct Transaction {
  225. pub clear_inputs: Vec<TransactionClearInput>,
  226. pub inputs: Vec<TransactionInput>,
  227. pub outputs: Vec<TransactionOutput>,
  228. pub clear_outputs: Vec<TransactionClearOutput>,
  229. }
  230. impl Encodable for Transaction {
  231. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  232. let mut len = 0;
  233. len += self.clear_inputs.encode(&mut s)?;
  234. len += self.inputs.encode(&mut s)?;
  235. len += self.outputs.encode(&mut s)?;
  236. len += self.clear_outputs.encode(&mut s)?;
  237. Ok(len)
  238. }
  239. }
  240. impl Decodable for Transaction {
  241. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  242. Ok(Self {
  243. clear_inputs: Decodable::decode(&mut d)?,
  244. inputs: Decodable::decode(&mut d)?,
  245. outputs: Decodable::decode(&mut d)?,
  246. clear_outputs: Decodable::decode(&mut d)?,
  247. })
  248. }
  249. }
  250. impl Transaction {
  251. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  252. let mut len = 0;
  253. len += self.clear_inputs.encode_without_signature(&mut s)?;
  254. len += self.inputs.encode_without_signature(&mut s)?;
  255. len += self.outputs.encode(&mut s)?;
  256. len += self.clear_outputs.encode(&mut s)?;
  257. Ok(len)
  258. }
  259. fn compute_value_commit(value: u64, blind: &jubjub::Fr) -> jubjub::SubgroupPoint {
  260. let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR
  261. * jubjub::Fr::from(value))
  262. + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR * blind);
  263. value_commit
  264. }
  265. pub fn verify(
  266. &self,
  267. mint_pvk: &groth16::PreparedVerifyingKey<Bls12>,
  268. spend_pvk: &groth16::PreparedVerifyingKey<Bls12>,
  269. ) -> bool {
  270. let mut valcom_total = jubjub::SubgroupPoint::identity();
  271. for input in &self.clear_inputs {
  272. valcom_total += Self::compute_value_commit(input.value, &input.valcom_blind);
  273. }
  274. for input in &self.inputs {
  275. if !verify_spend_proof(spend_pvk, &input.spend_proof, &input.revealed) {
  276. println!("spend fail");
  277. return false;
  278. }
  279. valcom_total += &input.revealed.value_commit;
  280. }
  281. for output in &self.outputs {
  282. if !verify_mint_proof(mint_pvk, &output.mint_proof, &output.revealed) {
  283. println!("mint fail");
  284. return false;
  285. }
  286. valcom_total -= &output.revealed.value_commit;
  287. }
  288. for output in &self.clear_outputs {
  289. valcom_total -= Self::compute_value_commit(output.value, &output.valcom_blind);
  290. }
  291. // Verify signatures
  292. let mut unsigned_tx_data = vec![];
  293. self.encode_without_signature(&mut unsigned_tx_data)
  294. .expect("TODO handle this");
  295. for input in &self.clear_inputs {
  296. let public = schnorr::PublicKey(input.signature_public.clone());
  297. if !public.verify(&unsigned_tx_data[..], &input.signature) {
  298. return false;
  299. }
  300. }
  301. for input in &self.inputs {
  302. let public = schnorr::PublicKey(input.revealed.signature_public.clone());
  303. if !public.verify(&unsigned_tx_data[..], &input.signature) {
  304. return false;
  305. }
  306. }
  307. valcom_total == jubjub::SubgroupPoint::identity()
  308. }
  309. }
  310. pub struct TransactionClearInput {
  311. pub value: u64,
  312. pub valcom_blind: jubjub::Fr,
  313. pub signature_public: jubjub::SubgroupPoint,
  314. pub signature: schnorr::Signature,
  315. }
  316. impl TransactionClearInput {
  317. fn from_partial(partial: PartialTransactionClearInput, signature: schnorr::Signature) -> Self {
  318. Self {
  319. value: partial.value,
  320. valcom_blind: partial.valcom_blind,
  321. signature_public: partial.signature_public,
  322. signature,
  323. }
  324. }
  325. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  326. let mut len = 0;
  327. len += self.value.encode(&mut s)?;
  328. len += self.valcom_blind.encode(&mut s)?;
  329. len += self.signature_public.encode(s)?;
  330. Ok(len)
  331. }
  332. }
  333. macro_rules! impl_vec_without_signature {
  334. ($type: ty) => {
  335. impl EncodableWithoutSignature for Vec<$type> {
  336. #[inline]
  337. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  338. let mut len = 0;
  339. len += VarInt(self.len() as u64).encode(&mut s)?;
  340. for c in self.iter() {
  341. len += c.encode_without_signature(&mut s)?;
  342. }
  343. Ok(len)
  344. }
  345. }
  346. };
  347. }
  348. impl_vec_without_signature!(TransactionClearInput);
  349. impl_vec!(TransactionClearInput);
  350. impl Encodable for TransactionClearInput {
  351. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  352. let mut len = 0;
  353. len += self.value.encode(&mut s)?;
  354. len += self.valcom_blind.encode(&mut s)?;
  355. len += self.signature_public.encode(&mut s)?;
  356. len += self.signature.encode(s)?;
  357. Ok(len)
  358. }
  359. }
  360. impl Decodable for TransactionClearInput {
  361. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  362. Ok(Self {
  363. value: Decodable::decode(&mut d)?,
  364. valcom_blind: Decodable::decode(&mut d)?,
  365. signature_public: Decodable::decode(&mut d)?,
  366. signature: Decodable::decode(d)?,
  367. })
  368. }
  369. }
  370. pub struct PartialTransactionClearInput {
  371. pub value: u64,
  372. pub valcom_blind: jubjub::Fr,
  373. pub signature_public: jubjub::SubgroupPoint,
  374. }
  375. impl_vec!(PartialTransactionClearInput);
  376. impl Encodable for PartialTransactionClearInput {
  377. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  378. let mut len = 0;
  379. len += self.value.encode(&mut s)?;
  380. len += self.valcom_blind.encode(&mut s)?;
  381. len += self.signature_public.encode(&mut s)?;
  382. Ok(len)
  383. }
  384. }
  385. impl Decodable for PartialTransactionClearInput {
  386. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  387. Ok(Self {
  388. value: Decodable::decode(&mut d)?,
  389. valcom_blind: Decodable::decode(&mut d)?,
  390. signature_public: Decodable::decode(&mut d)?,
  391. })
  392. }
  393. }
  394. pub struct PartialTransactionInput {
  395. pub spend_proof: groth16::Proof<Bls12>,
  396. pub revealed: SpendRevealedValues,
  397. }
  398. impl Encodable for PartialTransactionInput {
  399. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  400. let mut len = 0;
  401. len += self.spend_proof.encode(&mut s)?;
  402. len += self.revealed.encode(s)?;
  403. Ok(len)
  404. }
  405. }
  406. impl Decodable for PartialTransactionInput {
  407. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  408. Ok(Self {
  409. spend_proof: Decodable::decode(&mut d)?,
  410. revealed: Decodable::decode(d)?,
  411. })
  412. }
  413. }
  414. impl_vec!(PartialTransactionInput);
  415. pub struct TransactionInput {
  416. pub spend_proof: groth16::Proof<Bls12>,
  417. pub revealed: SpendRevealedValues,
  418. pub signature: schnorr::Signature,
  419. }
  420. impl TransactionInput {
  421. fn from_partial(partial: PartialTransactionInput, signature: schnorr::Signature) -> Self {
  422. Self {
  423. spend_proof: partial.spend_proof,
  424. revealed: partial.revealed,
  425. signature,
  426. }
  427. }
  428. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  429. let mut len = 0;
  430. len += self.spend_proof.encode(&mut s)?;
  431. len += self.revealed.encode(&mut s)?;
  432. Ok(len)
  433. }
  434. }
  435. trait EncodableWithoutSignature {
  436. fn encode_without_signature<S: io::Write>(&self, s: S) -> Result<usize>;
  437. }
  438. impl_vec_without_signature!(TransactionInput);
  439. impl Encodable for TransactionInput {
  440. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  441. let mut len = 0;
  442. len += self.spend_proof.encode(&mut s)?;
  443. len += self.revealed.encode(&mut s)?;
  444. len += self.signature.encode(s)?;
  445. Ok(len)
  446. }
  447. }
  448. impl Decodable for TransactionInput {
  449. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  450. Ok(Self {
  451. spend_proof: Decodable::decode(&mut d)?,
  452. revealed: Decodable::decode(&mut d)?,
  453. signature: Decodable::decode(d)?,
  454. })
  455. }
  456. }
  457. impl_vec!(TransactionInput);
  458. pub struct TransactionOutput {
  459. pub mint_proof: groth16::Proof<Bls12>,
  460. pub revealed: MintRevealedValues,
  461. pub enc_note: EncryptedNote,
  462. }
  463. impl_vec!(TransactionOutput);
  464. impl Encodable for TransactionOutput {
  465. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  466. let mut len = 0;
  467. len += self.mint_proof.encode(&mut s)?;
  468. len += self.revealed.encode(&mut s)?;
  469. len += self.enc_note.encode(&mut s)?;
  470. Ok(len)
  471. }
  472. }
  473. impl Decodable for TransactionOutput {
  474. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  475. Ok(Self {
  476. mint_proof: Decodable::decode(&mut d)?,
  477. revealed: Decodable::decode(&mut d)?,
  478. enc_note: Decodable::decode(&mut d)?,
  479. })
  480. }
  481. }
  482. pub struct TransactionClearOutput {
  483. pub value: u64,
  484. pub valcom_blind: jubjub::Fr,
  485. pub instructions: String,
  486. }
  487. impl_vec!(TransactionClearOutput);
  488. impl Encodable for TransactionClearOutput {
  489. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  490. let mut len = 0;
  491. len += self.value.encode(&mut s)?;
  492. len += self.valcom_blind.encode(&mut s)?;
  493. len += self.instructions.encode(s)?;
  494. Ok(len)
  495. }
  496. }
  497. impl Decodable for TransactionClearOutput {
  498. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  499. Ok(Self {
  500. value: Decodable::decode(&mut d)?,
  501. valcom_blind: Decodable::decode(&mut d)?,
  502. instructions: Decodable::decode(&mut d)?,
  503. })
  504. }
  505. }