]> Git Repo - VerusCoin.git/blame - src/gtest/test_circuit.cpp
Build fix
[VerusCoin.git] / src / gtest / test_circuit.cpp
CommitLineData
81469bbb
SB
1#include <gtest/gtest.h>
2#include "uint256.h"
3
81469bbb
SB
4#include "zcash/util.h"
5
6#include <boost/foreach.hpp>
7#include <boost/format.hpp>
8#include <boost/optional.hpp>
9
fee88353
JG
10#include <libsnark/common/default_types/r1cs_ppzksnark_pp.hpp>
11#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>
12#include <libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp>
13#include <libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp>
14
4d66f8f6 15#include "zcash/IncrementalMerkleTree.hpp"
81469bbb
SB
16
17using namespace libsnark;
4d66f8f6 18using namespace libzcash;
81469bbb
SB
19
20#include "zcash/circuit/utils.tcc"
4d66f8f6 21#include "zcash/circuit/merkle.tcc"
81469bbb
SB
22
23template<typename FieldT>
24void test_value_equals(uint64_t i) {
25 protoboard<FieldT> pb;
26 pb_variable_array<FieldT> num;
27 num.allocate(pb, 64, "");
28 num.fill_with_bits(pb, uint64_to_bool_vector(i));
29 pb.add_r1cs_constraint(r1cs_constraint<FieldT>(
30 packed_addition(num),
31 FieldT::one(),
32 FieldT::one() * i
33 ), "");
34 ASSERT_TRUE(pb.is_satisfied());
35}
36
37TEST(circuit, values)
38{
81469bbb
SB
39 typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
40 test_value_equals<FieldT>(0);
41 test_value_equals<FieldT>(1);
42 test_value_equals<FieldT>(3);
43 test_value_equals<FieldT>(5391);
44 test_value_equals<FieldT>(883128374);
45 test_value_equals<FieldT>(173419028459);
46 test_value_equals<FieldT>(2205843009213693953);
47}
48
49TEST(circuit, endianness)
50{
51 std::vector<unsigned char> before = {
52 0, 1, 2, 3, 4, 5, 6, 7,
53 8, 9, 10, 11, 12, 13, 14, 15,
54 16, 17, 18, 19, 20, 21, 22, 23,
55 24, 25, 26, 27, 28, 29, 30, 31,
56 32, 33, 34, 35, 36, 37, 38, 39,
57 40, 41, 42, 43, 44, 45, 46, 47,
58 48, 49, 50, 51, 52, 53, 54, 55,
59 56, 57, 58, 59, 60, 61, 62, 63
60 };
61 auto result = swap_endianness_u64(before);
62
63 std::vector<unsigned char> after = {
64 56, 57, 58, 59, 60, 61, 62, 63,
65 48, 49, 50, 51, 52, 53, 54, 55,
66 40, 41, 42, 43, 44, 45, 46, 47,
67 32, 33, 34, 35, 36, 37, 38, 39,
68 24, 25, 26, 27, 28, 29, 30, 31,
69 16, 17, 18, 19, 20, 21, 22, 23,
70 8, 9, 10, 11, 12, 13, 14, 15,
71 0, 1, 2, 3, 4, 5, 6, 7
72 };
73
74 EXPECT_EQ(after, result);
75
76 std::vector<unsigned char> bad = {0, 1, 2, 3};
77
78 ASSERT_THROW(swap_endianness_u64(bad), std::length_error);
79}
4d66f8f6
SB
80
81template<typename FieldT>
82bool test_merkle_gadget(
83 bool enforce_a,
84 bool enforce_b,
85 bool write_root_first
86)
87{
88 protoboard<FieldT> pb;
89 digest_variable<FieldT> root(pb, 256, "root");
90 pb.set_input_sizes(256);
91
92 digest_variable<FieldT> commitment1(pb, 256, "commitment1");
93 digest_variable<FieldT> commitment2(pb, 256, "commitment2");
94
95 pb_variable<FieldT> commitment1_read;
96 commitment1_read.allocate(pb);
97 pb_variable<FieldT> commitment2_read;
98 commitment2_read.allocate(pb);
99
100 merkle_tree_gadget<FieldT> mgadget1(pb, commitment1, root, commitment1_read);
101 merkle_tree_gadget<FieldT> mgadget2(pb, commitment2, root, commitment2_read);
102
103 commitment1.generate_r1cs_constraints();
104 commitment2.generate_r1cs_constraints();
105 root.generate_r1cs_constraints();
106 mgadget1.generate_r1cs_constraints();
107 mgadget2.generate_r1cs_constraints();
108
4fc309f0 109 SproutMerkleTree tree;
4d66f8f6
SB
110 uint256 commitment1_data = uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c");
111 uint256 commitment2_data = uint256S("59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7");
112 tree.append(commitment1_data);
113 auto wit1 = tree.witness();
114 tree.append(commitment2_data);
115 wit1.append(commitment2_data);
116 auto wit2 = tree.witness();
117 auto expected_root = tree.root();
118 tree.append(uint256S("3e243c8798678570bb8d42616c23a536af44be15c4eef073490c2a44ae5f32c3"));
119 auto unexpected_root = tree.root();
120 tree.append(uint256S("26d9b20c7f1c3d2528bbcd43cd63344b0afd3b6a0a8ebd37ec51cba34907bec7"));
121 auto badwit1 = tree.witness();
122 tree.append(uint256S("02c2467c9cd15e0d150f74cd636505ed675b0b71b66a719f6f52fdb49a5937bb"));
123 auto badwit2 = tree.witness();
124
125 // Perform the test
126
127 pb.val(commitment1_read) = enforce_a ? FieldT::one() : FieldT::zero();
128 pb.val(commitment2_read) = enforce_b ? FieldT::one() : FieldT::zero();
129
130 commitment1.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment1_data));
131 commitment2.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment2_data));
132
133 if (write_root_first) {
134 root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root));
135 }
136
137 mgadget1.generate_r1cs_witness(wit1.path());
138 mgadget2.generate_r1cs_witness(wit2.path());
139
140 // Overwrite with our expected root
141 root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root));
142
143 return pb.is_satisfied();
144}
145
146TEST(circuit, merkle_tree_gadget_weirdness)
147{
148 /*
149 The merkle tree gadget takes a leaf in the merkle tree (the Note commitment),
150 a merkle tree authentication path, and a root (anchor). It also takes a parameter
151 called read_success, which is used to determine if the commitment actually needs to
152 appear in the tree.
153
154 If two input notes use the same root (which our protocol does) then if `read_success`
155 is disabled on the first note but enabled on the second note (i.e., the first note
156 has value of zero and second note has nonzero value) then there is an edge case in
157 the witnessing behavior. The first witness will accidentally constrain the root to
158 equal null (the default value of the anchor) and the second witness will actually
159 copy the bits, violating the constraint system.
160
161 Notice that this edge case is not in the constraint system but in the witnessing
162 behavior.
163 */
164
4d66f8f6
SB
165 typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
166
167 // Test the normal case
168 ASSERT_TRUE(test_merkle_gadget<FieldT>(true, true, false));
169 ASSERT_TRUE(test_merkle_gadget<FieldT>(true, true, true));
170
171 // Test the case where the first commitment is enforced but the second isn't
172 // Works because the first read is performed before the second one
173 ASSERT_TRUE(test_merkle_gadget<FieldT>(true, false, false));
174 ASSERT_TRUE(test_merkle_gadget<FieldT>(true, false, true));
175
176 // Test the case where the first commitment isn't enforced but the second is
177 // Doesn't work because the first multipacker witnesses the existing root (which
178 // is null)
179 ASSERT_TRUE(!test_merkle_gadget<FieldT>(false, true, false));
180
181 // Test the last again, except this time write the root first.
182 ASSERT_TRUE(test_merkle_gadget<FieldT>(false, true, true));
183}
This page took 0.172101 seconds and 4 git commands to generate.