mod.rs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. pub mod builder;
  2. pub mod partial;
  3. use bellman::groth16;
  4. use bls12_381::Bls12;
  5. use group::Group;
  6. use std::io;
  7. use self::partial::{PartialTransactionClearInput, PartialTransactionInput};
  8. use crate::crypto::{
  9. note::EncryptedNote, schnorr, verify_mint_proof, verify_spend_proof, MintRevealedValues,
  10. SpendRevealedValues,
  11. };
  12. use crate::error::Result;
  13. use crate::impl_vec;
  14. use crate::serial::{Decodable, Encodable, VarInt};
  15. use crate::state;
  16. pub use self::builder::{
  17. TransactionBuilder, TransactionBuilderClearInputInfo, TransactionBuilderInputInfo,
  18. TransactionBuilderOutputInfo,
  19. };
  20. pub struct Transaction {
  21. pub clear_inputs: Vec<TransactionClearInput>,
  22. pub inputs: Vec<TransactionInput>,
  23. pub outputs: Vec<TransactionOutput>,
  24. }
  25. pub struct TransactionClearInput {
  26. pub value: u64,
  27. pub token_id: jubjub::Fr,
  28. pub valcom_blind: jubjub::Fr,
  29. pub asset_commit_blind: jubjub::Fr,
  30. pub signature_public: jubjub::SubgroupPoint,
  31. pub signature: schnorr::Signature,
  32. }
  33. pub struct TransactionInput {
  34. pub spend_proof: groth16::Proof<Bls12>,
  35. pub revealed: SpendRevealedValues,
  36. pub signature: schnorr::Signature,
  37. }
  38. pub struct TransactionOutput {
  39. pub mint_proof: groth16::Proof<Bls12>,
  40. pub revealed: MintRevealedValues,
  41. pub enc_note: EncryptedNote,
  42. }
  43. impl Transaction {
  44. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  45. let mut len = 0;
  46. len += self.clear_inputs.encode_without_signature(&mut s)?;
  47. len += self.inputs.encode_without_signature(&mut s)?;
  48. len += self.outputs.encode(s)?;
  49. Ok(len)
  50. }
  51. fn compute_pedersen_commit(value: jubjub::Fr, blind: &jubjub::Fr) -> jubjub::SubgroupPoint {
  52. (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR * value)
  53. + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR * blind)
  54. }
  55. fn verify_asset_commitments(&self) -> bool {
  56. assert_ne!(self.outputs.len(), 0);
  57. let asset_commit_value = self.outputs[0].revealed.asset_commit;
  58. let mut failed = self
  59. .inputs
  60. .iter()
  61. .any(|input| input.revealed.asset_commit != asset_commit_value);
  62. failed = failed
  63. || self
  64. .outputs
  65. .iter()
  66. .any(|output| output.revealed.asset_commit != asset_commit_value);
  67. failed = failed
  68. || self.clear_inputs.iter().any(|input| {
  69. Self::compute_pedersen_commit(input.token_id, &input.asset_commit_blind)
  70. != asset_commit_value
  71. });
  72. !failed
  73. }
  74. pub fn verify(
  75. &self,
  76. mint_pvk: &groth16::PreparedVerifyingKey<Bls12>,
  77. spend_pvk: &groth16::PreparedVerifyingKey<Bls12>,
  78. ) -> state::VerifyResult<()> {
  79. let mut valcom_total = jubjub::SubgroupPoint::identity();
  80. for input in &self.clear_inputs {
  81. let value = jubjub::Fr::from(input.value);
  82. valcom_total += Self::compute_pedersen_commit(value, &input.valcom_blind);
  83. }
  84. for (i, input) in self.inputs.iter().enumerate() {
  85. if !verify_spend_proof(spend_pvk, &input.spend_proof, &input.revealed) {
  86. return Err(state::VerifyFailed::SpendProof(i));
  87. }
  88. valcom_total += &input.revealed.value_commit;
  89. }
  90. for (i, output) in self.outputs.iter().enumerate() {
  91. if !verify_mint_proof(mint_pvk, &output.mint_proof, &output.revealed) {
  92. return Err(state::VerifyFailed::MintProof(i));
  93. }
  94. valcom_total -= &output.revealed.value_commit;
  95. }
  96. if valcom_total != jubjub::SubgroupPoint::identity() {
  97. return Err(state::VerifyFailed::MissingFunds);
  98. }
  99. // Verify asset commitments match
  100. if !self.verify_asset_commitments() {
  101. return Err(state::VerifyFailed::AssetMismatch);
  102. }
  103. // Verify signatures
  104. let mut unsigned_tx_data = vec![];
  105. self.encode_without_signature(&mut unsigned_tx_data)
  106. .expect("TODO handle this");
  107. for (i, input) in self.clear_inputs.iter().enumerate() {
  108. let public = schnorr::PublicKey(input.signature_public);
  109. if !public.verify(&unsigned_tx_data[..], &input.signature) {
  110. return Err(state::VerifyFailed::ClearInputSignature(i));
  111. }
  112. }
  113. for (i, input) in self.inputs.iter().enumerate() {
  114. let public = schnorr::PublicKey(input.revealed.signature_public);
  115. if !public.verify(&unsigned_tx_data[..], &input.signature) {
  116. return Err(state::VerifyFailed::InputSignature(i));
  117. }
  118. }
  119. Ok(())
  120. }
  121. }
  122. impl TransactionClearInput {
  123. fn from_partial(partial: PartialTransactionClearInput, signature: schnorr::Signature) -> Self {
  124. Self {
  125. value: partial.value,
  126. token_id: partial.token_id,
  127. valcom_blind: partial.valcom_blind,
  128. asset_commit_blind: partial.asset_commit_blind,
  129. signature_public: partial.signature_public,
  130. signature,
  131. }
  132. }
  133. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  134. let mut len = 0;
  135. len += self.value.encode(&mut s)?;
  136. len += self.token_id.encode(&mut s)?;
  137. len += self.valcom_blind.encode(&mut s)?;
  138. len += self.asset_commit_blind.encode(&mut s)?;
  139. len += self.signature_public.encode(s)?;
  140. Ok(len)
  141. }
  142. }
  143. impl TransactionInput {
  144. fn from_partial(partial: PartialTransactionInput, signature: schnorr::Signature) -> Self {
  145. Self {
  146. spend_proof: partial.spend_proof,
  147. revealed: partial.revealed,
  148. signature,
  149. }
  150. }
  151. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  152. let mut len = 0;
  153. len += self.spend_proof.encode(&mut s)?;
  154. len += self.revealed.encode(&mut s)?;
  155. Ok(len)
  156. }
  157. }
  158. impl Encodable for Transaction {
  159. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  160. let mut len = 0;
  161. len += self.clear_inputs.encode(&mut s)?;
  162. len += self.inputs.encode(&mut s)?;
  163. len += self.outputs.encode(s)?;
  164. Ok(len)
  165. }
  166. }
  167. impl Decodable for Transaction {
  168. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  169. Ok(Self {
  170. clear_inputs: Decodable::decode(&mut d)?,
  171. inputs: Decodable::decode(&mut d)?,
  172. outputs: Decodable::decode(d)?,
  173. })
  174. }
  175. }
  176. impl Encodable for TransactionClearInput {
  177. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  178. let mut len = 0;
  179. len += self.value.encode(&mut s)?;
  180. len += self.token_id.encode(&mut s)?;
  181. len += self.valcom_blind.encode(&mut s)?;
  182. len += self.asset_commit_blind.encode(&mut s)?;
  183. len += self.signature_public.encode(&mut s)?;
  184. len += self.signature.encode(s)?;
  185. Ok(len)
  186. }
  187. }
  188. impl Decodable for TransactionClearInput {
  189. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  190. Ok(Self {
  191. value: Decodable::decode(&mut d)?,
  192. token_id: Decodable::decode(&mut d)?,
  193. valcom_blind: Decodable::decode(&mut d)?,
  194. asset_commit_blind: Decodable::decode(&mut d)?,
  195. signature_public: Decodable::decode(&mut d)?,
  196. signature: Decodable::decode(d)?,
  197. })
  198. }
  199. }
  200. impl Encodable for TransactionInput {
  201. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  202. let mut len = 0;
  203. len += self.spend_proof.encode(&mut s)?;
  204. len += self.revealed.encode(&mut s)?;
  205. len += self.signature.encode(s)?;
  206. Ok(len)
  207. }
  208. }
  209. impl Decodable for TransactionInput {
  210. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  211. Ok(Self {
  212. spend_proof: Decodable::decode(&mut d)?,
  213. revealed: Decodable::decode(&mut d)?,
  214. signature: Decodable::decode(d)?,
  215. })
  216. }
  217. }
  218. impl Encodable for TransactionOutput {
  219. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  220. let mut len = 0;
  221. len += self.mint_proof.encode(&mut s)?;
  222. len += self.revealed.encode(&mut s)?;
  223. len += self.enc_note.encode(&mut s)?;
  224. Ok(len)
  225. }
  226. }
  227. impl Decodable for TransactionOutput {
  228. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  229. Ok(Self {
  230. mint_proof: Decodable::decode(&mut d)?,
  231. revealed: Decodable::decode(&mut d)?,
  232. enc_note: Decodable::decode(&mut d)?,
  233. })
  234. }
  235. }
  236. trait EncodableWithoutSignature {
  237. fn encode_without_signature<S: io::Write>(&self, s: S) -> Result<usize>;
  238. }
  239. macro_rules! impl_vec_without_signature {
  240. ($type: ty) => {
  241. impl EncodableWithoutSignature for Vec<$type> {
  242. #[inline]
  243. fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
  244. let mut len = 0;
  245. len += VarInt(self.len() as u64).encode(&mut s)?;
  246. for c in self.iter() {
  247. len += c.encode_without_signature(&mut s)?;
  248. }
  249. Ok(len)
  250. }
  251. }
  252. };
  253. }
  254. impl_vec_without_signature!(TransactionClearInput);
  255. impl_vec_without_signature!(TransactionInput);
  256. impl_vec!(TransactionClearInput);
  257. impl_vec!(TransactionInput);
  258. impl_vec!(TransactionOutput);