snarkvm_ledger_coinbase/helpers/coinbase_solution/
mod.rs1mod bytes;
16mod serialize;
17mod string;
18
19use super::*;
20
21use indexmap::IndexMap;
22
23#[derive(Clone, Eq, PartialEq)]
25pub struct CoinbaseSolution<N: Network> {
26 solutions: IndexMap<PuzzleCommitment<N>, ProverSolution<N>>,
28}
29
30impl<N: Network> CoinbaseSolution<N> {
31 pub fn new(solutions: Vec<ProverSolution<N>>) -> Result<Self> {
33 ensure!(!solutions.is_empty(), "There are no solutions to verify for the coinbase puzzle");
35 if solutions.len() > N::MAX_SOLUTIONS {
37 bail!(
38 "The solutions exceed the allowed number of partial solutions. ({} > {})",
39 solutions.len(),
40 N::MAX_SOLUTIONS
41 );
42 }
43 if has_duplicates(solutions.iter().map(|s| s.commitment())) {
45 bail!("The solutions contain duplicate puzzle commitments");
46 }
47 Ok(Self { solutions: solutions.into_iter().map(|solution| (solution.commitment(), solution)).collect() })
49 }
50
51 pub fn puzzle_commitments(&self) -> impl '_ + Iterator<Item = &PuzzleCommitment<N>> {
53 self.solutions.keys()
54 }
55
56 pub fn len(&self) -> usize {
58 self.solutions.len()
59 }
60
61 pub fn is_empty(&self) -> bool {
63 self.solutions.is_empty()
64 }
65
66 pub fn get_solution(&self, puzzle_commitment: &PuzzleCommitment<N>) -> Option<&ProverSolution<N>> {
68 self.solutions.get(puzzle_commitment)
69 }
70
71 pub fn to_combined_proof_target(&self) -> Result<u128> {
73 self.solutions.values().try_fold(0u128, |combined, solution| {
75 combined.checked_add(solution.to_target()? as u128).ok_or_else(|| anyhow!("Combined target overflowed"))
76 })
77 }
78
79 pub fn to_accumulator_point(&self) -> Result<Field<N>> {
81 let mut challenge_points = hash_commitments(self.solutions.keys().map(|pcm| **pcm))?;
82 ensure!(challenge_points.len() == self.solutions.len() + 1, "Invalid number of challenge points");
83
84 match challenge_points.pop() {
86 Some(point) => Ok(Field::new(point)),
87 None => bail!("Missing the accumulator challenge point"),
88 }
89 }
90}
91
92impl<N: Network> Deref for CoinbaseSolution<N> {
93 type Target = IndexMap<PuzzleCommitment<N>, ProverSolution<N>>;
94
95 fn deref(&self) -> &Self::Target {
96 &self.solutions
97 }
98}