mod.rs 9.5 KB

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