tx.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. use darkfi::{crypto::Proof, Result, VerifyFailed::ProofVerifyFailed};
  2. use darkfi_serial::Encodable;
  3. use darkfi_sdk::{
  4. crypto::{
  5. schnorr::{SchnorrPublic, Signature},
  6. PublicKey,
  7. },
  8. pasta::pallas,
  9. tx::ContractCall,
  10. };
  11. use log::debug;
  12. use crate::{
  13. contract::{dao, example, money},
  14. note::EncryptedNote2,
  15. schema::WalletCache,
  16. util::{sign, StateRegistry, ZkContractInfo, ZkContractTable},
  17. };
  18. macro_rules! zip {
  19. ($x: expr) => ($x);
  20. ($x: expr, $($y: expr), +) => (
  21. $x.iter().zip(
  22. zip!($($y), +))
  23. )
  24. }
  25. pub struct Transaction {
  26. pub calls: Vec<ContractCall>,
  27. pub proofs: Vec<Vec<Proof>>,
  28. pub signatures: Vec<Vec<Signature>>,
  29. }
  30. impl Transaction {
  31. /// Verify ZK contracts for the entire tx
  32. /// In real code, we could parallelize this for loop
  33. /// TODO: fix use of unwrap with Result type stuff
  34. pub fn zk_verify(
  35. &self,
  36. zk_bins: &ZkContractTable,
  37. zkpub_table: &Vec<Vec<(String, Vec<pallas::Base>)>>,
  38. ) -> Result<()> {
  39. assert_eq!(
  40. self.calls.len(),
  41. self.proofs.len(),
  42. "calls.len()={} and proofs.len()={} do not match",
  43. self.calls.len(),
  44. self.proofs.len()
  45. );
  46. assert_eq!(
  47. self.calls.len(),
  48. zkpub_table.len(),
  49. "calls.len()={} and zkpub_table.len()={} do not match",
  50. self.calls.len(),
  51. zkpub_table.len()
  52. );
  53. for (call, (proofs, pubvals)) in zip!(self.calls, self.proofs, zkpub_table) {
  54. assert_eq!(
  55. proofs.len(),
  56. pubvals.len(),
  57. "proofs.len()={} and pubvals.len()={} do not match",
  58. proofs.len(),
  59. pubvals.len()
  60. );
  61. for (i, (proof, (key, public_vals))) in proofs.iter().zip(pubvals.iter()).enumerate() {
  62. match zk_bins.lookup(key).unwrap() {
  63. ZkContractInfo::Binary(info) => {
  64. let verifying_key = &info.verifying_key;
  65. let verify_result = proof.verify(verifying_key, public_vals);
  66. if verify_result.is_err() {
  67. return Err(ProofVerifyFailed(key.to_string()).into())
  68. }
  69. //assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
  70. }
  71. ZkContractInfo::Native(info) => {
  72. let verifying_key = &info.verifying_key;
  73. let verify_result = proof.verify(verifying_key, public_vals);
  74. if verify_result.is_err() {
  75. return Err(ProofVerifyFailed(key.to_string()).into())
  76. }
  77. //assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
  78. }
  79. };
  80. debug!(target: "demo", "zk_verify({}) passed [i={}]", key, i);
  81. }
  82. }
  83. Ok(())
  84. }
  85. pub fn verify_sigs(&self, sigpub_table: &Vec<Vec<pallas::Point>>) -> Result<()> {
  86. let mut tx_data = Vec::new();
  87. self.calls.encode(&mut tx_data)?;
  88. self.proofs.encode(&mut tx_data)?;
  89. // TODO: Hash it and use the hash as the signing data
  90. // let sighash = ...
  91. for (i, (signatures, signature_public_keys)) in
  92. self.signatures.iter().zip(sigpub_table.iter()).enumerate()
  93. {
  94. for (signature_pub_key, signature) in signature_public_keys.iter().zip(signatures) {
  95. let signature_pub_key = PublicKey::from(*signature_pub_key);
  96. let verify_result = signature_pub_key.verify(&tx_data[..], &signature);
  97. assert!(verify_result, "verify sigs[{}] failed", i);
  98. }
  99. debug!(target: "demo", "verify_sigs({}) passed", i);
  100. }
  101. Ok(())
  102. }
  103. }