mod.rs 9.3 KB

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