stake_v1.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. //! This API is crufty. Please rework it into something nice to read and nice to use.
  19. use darkfi::{
  20. zk::{Proof, ProvingKey},
  21. zkas::ZkBinary,
  22. Result,
  23. };
  24. use darkfi_money_contract::{
  25. client::{ConsensusNote, OwnCoin},
  26. model::{ConsensusInput, ConsensusOutput, ConsensusStakeParamsV1},
  27. };
  28. use darkfi_sdk::{
  29. crypto::{
  30. note::AeadEncryptedNote, pasta_prelude::*, MerkleNode, Nullifier, PublicKey, SecretKey,
  31. DARK_TOKEN_ID,
  32. },
  33. pasta::pallas,
  34. };
  35. use log::{debug, info};
  36. use rand::rngs::OsRng;
  37. use crate::client::common::{create_consensus_mint_proof, ConsensusMintOutputInfo};
  38. pub struct ConsensusStakeCallDebris {
  39. pub params: ConsensusStakeParamsV1,
  40. pub proofs: Vec<Proof>,
  41. pub signature_secret: SecretKey,
  42. }
  43. /// Struct holding necessary information to build a `Consensus::StakeV1` contract call.
  44. pub struct ConsensusStakeCallBuilder {
  45. /// `OwnCoin` we're given to use in this builder
  46. pub coin: OwnCoin,
  47. /// Epoch staked coin is minted
  48. pub epoch: u64,
  49. /// Blinding factor for value commitment
  50. pub value_blind: pallas::Scalar,
  51. /// Revealed nullifier
  52. pub nullifier: Nullifier,
  53. /// Revealed Merkle root
  54. pub merkle_root: MerkleNode,
  55. /// `ConsensusMint_V1` zkas circuit ZkBinary
  56. pub mint_zkbin: ZkBinary,
  57. /// Proving key for the `ConsensusMint_V1` zk circuit
  58. pub mint_pk: ProvingKey,
  59. }
  60. impl ConsensusStakeCallBuilder {
  61. pub fn build(&self) -> Result<ConsensusStakeCallDebris> {
  62. debug!("Building Consensus::StakeV1 contract call");
  63. assert!(self.coin.note.value != 0);
  64. assert!(self.coin.note.token_id == *DARK_TOKEN_ID);
  65. debug!("Building anonymous output");
  66. let serial = pallas::Base::random(&mut OsRng);
  67. let coin_blind = pallas::Base::random(&mut OsRng);
  68. let public_key = PublicKey::from_secret(self.coin.secret);
  69. let output = ConsensusMintOutputInfo {
  70. value: self.coin.note.value,
  71. epoch: self.epoch,
  72. public_key,
  73. value_blind: self.value_blind,
  74. serial,
  75. coin_blind,
  76. };
  77. debug!("Finished building output");
  78. info!("Creating stake mint proof for output");
  79. let (proof, public_inputs) =
  80. create_consensus_mint_proof(&self.mint_zkbin, &self.mint_pk, &output)?;
  81. // Encrypted note
  82. let note = ConsensusNote {
  83. serial,
  84. value: output.value,
  85. epoch: self.epoch,
  86. coin_blind,
  87. value_blind: self.value_blind,
  88. reward: 0,
  89. reward_blind: self.value_blind,
  90. };
  91. let encrypted_note = AeadEncryptedNote::encrypt(&note, &output.public_key, &mut OsRng)?;
  92. let output = ConsensusOutput {
  93. value_commit: public_inputs.value_commit,
  94. coin: public_inputs.coin,
  95. note: encrypted_note,
  96. };
  97. let input = ConsensusInput {
  98. epoch: self.epoch,
  99. coin: self.coin.coin,
  100. value_commit: public_inputs.value_commit,
  101. nullifier: self.nullifier,
  102. merkle_root: self.merkle_root,
  103. signature_public: public_key,
  104. };
  105. // We now fill this with necessary stuff
  106. let params = ConsensusStakeParamsV1 { input, output };
  107. let proofs = vec![proof];
  108. // Now we should have all the params and zk proof.
  109. // We return it all and let the caller deal with it.
  110. let debris =
  111. ConsensusStakeCallDebris { params, proofs, signature_secret: self.coin.secret };
  112. Ok(debris)
  113. }
  114. }