mod.rs 9.3 KB

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