consensus_proposal.rs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. use std::time::Instant;
  19. use darkfi::{tx::Transaction, Result};
  20. use darkfi_consensus_contract::{
  21. client::proposal_v1::ConsensusProposalCallBuilder,
  22. model::{ConsensusProposalParamsV1, REWARD},
  23. ConsensusFunction,
  24. };
  25. use darkfi_money_contract::{client::ConsensusOwnCoin, CONSENSUS_CONTRACT_ZKAS_PROPOSAL_NS_V1};
  26. use darkfi_sdk::{
  27. blockchain::Slot,
  28. crypto::{MerkleNode, SecretKey, CONSENSUS_CONTRACT_ID},
  29. ContractCall,
  30. };
  31. use darkfi_serial::{serialize, Encodable};
  32. use log::info;
  33. use rand::rngs::OsRng;
  34. use super::{Holder, TestHarness, TxAction};
  35. impl TestHarness {
  36. pub async fn proposal(
  37. &mut self,
  38. holder: &Holder,
  39. slot: Slot,
  40. staked_oc: &ConsensusOwnCoin,
  41. ) -> Result<(Transaction, ConsensusProposalParamsV1, SecretKey, SecretKey)> {
  42. let wallet = self.holders.get(holder).unwrap();
  43. let (proposal_pk, proposal_zkbin) =
  44. self.proving_keys.get(&CONSENSUS_CONTRACT_ZKAS_PROPOSAL_NS_V1.to_string()).unwrap();
  45. let tx_action_benchmark =
  46. self.tx_action_benchmarks.get_mut(&TxAction::ConsensusProposal).unwrap();
  47. let timer = Instant::now();
  48. // Proposals always extend genesis block
  49. let fork_hash = self.genesis_block;
  50. // Building Consensus::Propose params
  51. let proposal_call_debris = ConsensusProposalCallBuilder {
  52. owncoin: staked_oc.clone(),
  53. slot,
  54. fork_hash,
  55. fork_previous_hash: fork_hash,
  56. merkle_tree: wallet.consensus_staked_merkle_tree.clone(),
  57. proposal_zkbin: proposal_zkbin.clone(),
  58. proposal_pk: proposal_pk.clone(),
  59. }
  60. .build()?;
  61. let (params, proofs, output_keypair, signature_secret_key) = (
  62. proposal_call_debris.params,
  63. proposal_call_debris.proofs,
  64. proposal_call_debris.keypair,
  65. proposal_call_debris.signature_secret,
  66. );
  67. let mut data = vec![ConsensusFunction::ProposalV1 as u8];
  68. params.encode(&mut data)?;
  69. let call = ContractCall { contract_id: *CONSENSUS_CONTRACT_ID, data };
  70. let calls = vec![call];
  71. let proofs = vec![proofs];
  72. let mut tx = Transaction { calls, proofs, signatures: vec![] };
  73. let sigs = tx.create_sigs(&mut OsRng, &[signature_secret_key])?;
  74. tx.signatures = vec![sigs];
  75. tx_action_benchmark.creation_times.push(timer.elapsed());
  76. // Calculate transaction sizes
  77. let encoded: Vec<u8> = serialize(&tx);
  78. let size = std::mem::size_of_val(&*encoded);
  79. tx_action_benchmark.sizes.push(size);
  80. let base58 = bs58::encode(&encoded).into_string();
  81. let size = std::mem::size_of_val(&*base58);
  82. tx_action_benchmark.broadcasted_sizes.push(size);
  83. Ok((tx, params, signature_secret_key, output_keypair.secret))
  84. }
  85. pub async fn execute_proposal_tx(
  86. &mut self,
  87. holder: &Holder,
  88. tx: &Transaction,
  89. params: &ConsensusProposalParamsV1,
  90. slot: u64,
  91. ) -> Result<()> {
  92. let wallet = self.holders.get_mut(holder).unwrap();
  93. let tx_action_benchmark =
  94. self.tx_action_benchmarks.get_mut(&TxAction::ConsensusProposal).unwrap();
  95. let timer = Instant::now();
  96. wallet.validator.read().await.add_test_producer_transaction(tx, slot, true).await?;
  97. wallet.consensus_staked_merkle_tree.append(MerkleNode::from(params.output.coin.inner()));
  98. tx_action_benchmark.verify_times.push(timer.elapsed());
  99. Ok(())
  100. }
  101. // Execute a proposal transaction and gather rewarded coin
  102. pub async fn execute_proposal(
  103. &mut self,
  104. holders: &[Holder],
  105. holder: &Holder,
  106. current_slot: u64,
  107. slot: Slot,
  108. staked_oc: &ConsensusOwnCoin,
  109. ) -> Result<ConsensusOwnCoin> {
  110. info!(target: "consensus", "[{holder:?}] ====================");
  111. info!(target: "consensus", "[{holder:?}] Building proposal tx");
  112. info!(target: "consensus", "[{holder:?}] ====================");
  113. let (
  114. proposal_tx,
  115. proposal_params,
  116. _proposal_signing_secret_key,
  117. proposal_decryption_secret_key,
  118. ) = self.proposal(holder, slot, staked_oc).await?;
  119. for h in holders {
  120. info!(target: "consensus", "[{h:?}] ================================");
  121. info!(target: "consensus", "[{h:?}] Executing {holder:?} proposal tx");
  122. info!(target: "consensus", "[{h:?}] ================================");
  123. self.execute_proposal_tx(h, &proposal_tx, &proposal_params, current_slot).await?;
  124. }
  125. self.assert_trees(holders);
  126. // Gather new staked owncoin which includes the reward
  127. let rewarded_staked_oc = self.gather_consensus_staked_owncoin(
  128. holder,
  129. &proposal_params.output,
  130. Some(proposal_decryption_secret_key),
  131. )?;
  132. // Verify values match
  133. assert!((staked_oc.note.value + REWARD) == rewarded_staked_oc.note.value);
  134. Ok(rewarded_staked_oc)
  135. }
  136. pub async fn execute_erroneous_proposal_tx(
  137. &mut self,
  138. holder: &Holder,
  139. tx: &Transaction,
  140. slot: u64,
  141. ) -> Result<()> {
  142. let wallet = self.holders.get_mut(holder).unwrap();
  143. let tx_action_benchmark =
  144. self.tx_action_benchmarks.get_mut(&TxAction::ConsensusProposal).unwrap();
  145. let timer = Instant::now();
  146. assert!(wallet
  147. .validator
  148. .read()
  149. .await
  150. .add_test_producer_transaction(tx, slot, true)
  151. .await
  152. .is_err());
  153. tx_action_benchmark.verify_times.push(timer.elapsed());
  154. Ok(())
  155. }
  156. }