snarkvm_posw/
lib.rs

1// Copyright (C) 2019-2021 Aleo Systems Inc.
2// This file is part of the snarkVM library.
3
4// The snarkVM library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The snarkVM library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the snarkVM library. If not, see <https://www.gnu.org/licenses/>.
16
17pub mod circuit;
18
19mod posw;
20use posw::{HG, M};
21
22pub mod error;
23
24use snarkvm_algorithms::snark;
25use snarkvm_curves::{bls12_377::Bls12_377, traits::PairingEngine};
26use snarkvm_dpc::block::{
27    merkle_root_with_subroots,
28    pedersen_merkle_root,
29    MerkleRootHash,
30    PedersenMerkleRootHash,
31    MASKED_TREE_DEPTH,
32};
33
34/// GM17 type alias for the PoSW circuit
35#[deprecated]
36pub type GM17<E> = snark::gm17::GM17<E, PoswCircuit<<E as PairingEngine>::Fr>, Vec<<E as PairingEngine>::Fr>>;
37
38/// PoSW instantiated over BLS12-377 with Marlin.
39pub type PoswMarlin = Posw<Marlin<Bls12_377>, Bls12_377>;
40
41/// Marlin proof system on PoSW
42pub type Marlin<E> =
43    snarkvm_marlin::snark::MarlinSystem<E, PoswCircuit<<E as PairingEngine>::Fr>, Vec<<E as PairingEngine>::Fr>>;
44
45/// A generic PoSW.
46pub type Posw<S, E> = posw::Posw<S, <E as PairingEngine>::Fr, M, HG, params::PoSWParams>;
47
48/// Instantiate the circuit with the CRH to Fq.
49type PoswCircuit<F> = circuit::POSWCircuit<F, M, HG, params::PoSWParams>;
50
51// Do not leak private type
52mod params {
53    #[derive(Clone, Debug, PartialEq, Eq)]
54    pub struct PoSWParams;
55    impl crate::circuit::POSWCircuitParameters for PoSWParams {
56        // A 32 byte mask is sufficient for Pedersen hashes on BLS12-377, leaves and the root
57        const MASK_LENGTH: usize = 32;
58    }
59}
60
61/// Subtree calculation
62pub fn txids_to_roots(transaction_ids: &[[u8; 32]]) -> (MerkleRootHash, PedersenMerkleRootHash, Vec<[u8; 32]>) {
63    let (root, subroots) = merkle_root_with_subroots(transaction_ids, MASKED_TREE_DEPTH);
64    let mut merkle_root_bytes = [0u8; 32];
65    merkle_root_bytes[..].copy_from_slice(&root);
66
67    (
68        MerkleRootHash(merkle_root_bytes),
69        pedersen_merkle_root(&subroots),
70        subroots,
71    )
72}
73
74#[cfg(test)]
75mod tests {
76    use std::sync::atomic::AtomicBool;
77
78    use super::*;
79    use rand::SeedableRng;
80    use rand_xorshift::XorShiftRng;
81    use snarkvm_algorithms::traits::SNARK;
82    use snarkvm_utilities::FromBytes;
83
84    #[test]
85    fn test_load_verify_only() {
86        let _params = PoswMarlin::verify_only().unwrap();
87    }
88
89    #[test]
90    fn test_load() {
91        let _params = PoswMarlin::load().unwrap();
92    }
93
94    #[test]
95    #[allow(deprecated)]
96    fn test_posw_gm17() {
97        let rng = &mut XorShiftRng::seed_from_u64(1234567);
98
99        // PoSW instantiated over BLS12-377 with GM17.
100        pub type PoswGM17 = Posw<GM17<Bls12_377>, Bls12_377>;
101
102        // run the trusted setup
103        let posw = PoswGM17::setup(rng).unwrap();
104        // super low difficulty so we find a solution immediately
105        let difficulty_target = 0xFFFF_FFFF_FFFF_FFFF_u64;
106
107        let transaction_ids = vec![[1u8; 32]; 8];
108        let (_, pedersen_merkle_root, subroots) = txids_to_roots(&transaction_ids);
109
110        // generate the proof
111        let (nonce, proof) = posw
112            .mine(
113                &subroots,
114                difficulty_target,
115                &AtomicBool::new(false),
116                &mut rand::thread_rng(),
117                std::u32::MAX,
118            )
119            .unwrap();
120        assert_eq!(proof.len(), 193); // NOTE: GM17 compressed serialization
121
122        let proof = <GM17<Bls12_377> as SNARK>::Proof::read(&proof[..]).unwrap();
123        posw.verify(nonce, &proof, &pedersen_merkle_root).unwrap();
124    }
125
126    #[test]
127    fn test_posw_marlin() {
128        let rng = &mut XorShiftRng::seed_from_u64(1234567);
129
130        // run the trusted setup
131        let universal_srs = snarkvm_marlin::MarlinTestnet1::universal_setup(10000, 10000, 100000, rng).unwrap();
132
133        // run the deterministic setup
134        let posw = PoswMarlin::index(universal_srs).unwrap();
135
136        // super low difficulty so we find a solution immediately
137        let difficulty_target = 0xFFFF_FFFF_FFFF_FFFF_u64;
138
139        let transaction_ids = vec![[1u8; 32]; 8];
140        let (_, pedersen_merkle_root, subroots) = txids_to_roots(&transaction_ids);
141
142        // generate the proof
143        let (nonce, proof) = posw
144            .mine(
145                &subroots,
146                difficulty_target,
147                &AtomicBool::new(false),
148                &mut rand::thread_rng(),
149                std::u32::MAX,
150            )
151            .unwrap();
152
153        assert_eq!(proof.len(), 972); // NOTE: Marlin proofs use compressed serialization
154
155        let proof = <Marlin<Bls12_377> as SNARK>::Proof::read_le(&proof[..]).unwrap();
156        posw.verify(nonce, &proof, &pedersen_merkle_root).unwrap();
157    }
158}