diff --git a/src/Makefile.am b/src/Makefile.am index 1ea46f643..aab999fa2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,7 +77,8 @@ LIBZEROCASH_H = \ zcash/Address.hpp \ zcash/JoinSplit.hpp \ zcash/Note.hpp \ - zcash/prf.h + zcash/prf.h \ + zcash/util.h .PHONY: FORCE # bitcoin core # @@ -411,7 +412,8 @@ libzerocash_a_SOURCES = \ zcash/Address.cpp \ zcash/JoinSplit.cpp \ zcash/Note.cpp \ - zcash/prf.cpp + zcash/prf.cpp \ + zcash/util.cpp libzerocash_a_CPPFLAGS = -fPIC -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -std=c++11 -pipe -O2 -O0 -g -Wstack-protector -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index 2bd780608..81e3f5744 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -8,7 +8,8 @@ zcash_gtest_SOURCES = \ gtest/test_checktransaction.cpp \ gtest/test_joinsplit.cpp \ gtest/test_noteencryption.cpp \ - gtest/test_merkletree.cpp + gtest/test_merkletree.cpp \ + gtest/test_circuit.cpp zcash_gtest_LDADD = -lgtest $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) diff --git a/src/gtest/test_circuit.cpp b/src/gtest/test_circuit.cpp new file mode 100644 index 000000000..26004e045 --- /dev/null +++ b/src/gtest/test_circuit.cpp @@ -0,0 +1,78 @@ +#include +#include "uint256.h" + +#include "zerocash/utils/util.h" +#include "zcash/util.h" + +#include +#include +#include + +#include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp" +#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp" +#include "libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp" +#include "libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp" + +using namespace libsnark; +using namespace libzerocash; + +#include "zcash/circuit/utils.tcc" + +template +void test_value_equals(uint64_t i) { + protoboard pb; + pb_variable_array num; + num.allocate(pb, 64, ""); + num.fill_with_bits(pb, uint64_to_bool_vector(i)); + pb.add_r1cs_constraint(r1cs_constraint( + packed_addition(num), + FieldT::one(), + FieldT::one() * i + ), ""); + ASSERT_TRUE(pb.is_satisfied()); +} + +TEST(circuit, values) +{ + default_r1cs_ppzksnark_pp::init_public_params(); + typedef Fr FieldT; + test_value_equals(0); + test_value_equals(1); + test_value_equals(3); + test_value_equals(5391); + test_value_equals(883128374); + test_value_equals(173419028459); + test_value_equals(2205843009213693953); +} + +TEST(circuit, endianness) +{ + std::vector before = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63 + }; + auto result = swap_endianness_u64(before); + + std::vector after = { + 56, 57, 58, 59, 60, 61, 62, 63, + 48, 49, 50, 51, 52, 53, 54, 55, + 40, 41, 42, 43, 44, 45, 46, 47, + 32, 33, 34, 35, 36, 37, 38, 39, + 24, 25, 26, 27, 28, 29, 30, 31, + 16, 17, 18, 19, 20, 21, 22, 23, + 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7 + }; + + EXPECT_EQ(after, result); + + std::vector bad = {0, 1, 2, 3}; + + ASSERT_THROW(swap_endianness_u64(bad), std::length_error); +} diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 9422e6215..05da1e87a 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -3,6 +3,7 @@ #include "sodium.h" #include "zerocash/utils/util.h" +#include "zcash/util.h" #include diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp index b17a2fb40..afef81458 100644 --- a/src/zcash/Note.cpp +++ b/src/zcash/Note.cpp @@ -1,11 +1,12 @@ #include "Note.hpp" #include "prf.h" #include "crypto/sha256.h" -#include "zerocash/utils/util.h" #include "version.h" #include "streams.h" +#include "zcash/util.h" + namespace libzcash { Note::Note() { @@ -22,8 +23,7 @@ uint256 Note::cm() const { hasher.Write(&discriminant, 1); hasher.Write(a_pk.begin(), 32); - std::vector value_vec(sizeof(value), 0); - libzerocash::convertIntToBytesVector(value, value_vec); + auto value_vec = convertIntToVectorLE(value); hasher.Write(&value_vec[0], value_vec.size()); hasher.Write(rho.begin(), 32); diff --git a/src/zcash/circuit/utils.tcc b/src/zcash/circuit/utils.tcc index efde63bc2..24ffe1b94 100644 --- a/src/zcash/circuit/utils.tcc +++ b/src/zcash/circuit/utils.tcc @@ -29,8 +29,7 @@ std::vector uint256_to_bool_vector(uint256 input) { } std::vector uint64_to_bool_vector(uint64_t input) { - std::vector num_bv(8, 0); - libzerocash::convertIntToBytesVector(input, num_bv); + auto num_bv = convertIntToVectorLE(input); std::vector num_v(64, 0); libzerocash::convertBytesVectorToVector(num_bv, num_v); @@ -47,9 +46,26 @@ void insert_uint64(std::vector& into, uint64_t from) { into.insert(into.end(), num.begin(), num.end()); } +template +T swap_endianness_u64(T v) { + if (v.size() != 64) { + throw std::length_error("invalid bit length for 64-bit unsigned integer"); + } + + for (size_t i = 0; i < 4; i++) { + for (size_t j = 0; j < 8; j++) { + std::swap(v[i*8 + j], v[((7-i)*8)+j]); + } + } + + return v; +} + template -linear_combination packed_addition(pb_variable_array& input) { +linear_combination packed_addition(pb_variable_array input) { + auto input_swapped = swap_endianness_u64(input); + return pb_packing_sum(pb_variable_array( - input.rbegin(), input.rend() + input_swapped.rbegin(), input_swapped.rend() )); } diff --git a/src/zcash/util.cpp b/src/zcash/util.cpp new file mode 100644 index 000000000..b4f33d774 --- /dev/null +++ b/src/zcash/util.cpp @@ -0,0 +1,12 @@ +#include "zcash/util.h" +#include + +std::vector convertIntToVectorLE(const uint64_t val_int) { + std::vector bytes; + + for(size_t i = 0; i < 8; i++) { + bytes.push_back(val_int >> (i * 8)); + } + + return bytes; +} diff --git a/src/zcash/util.h b/src/zcash/util.h new file mode 100644 index 000000000..94aed3c72 --- /dev/null +++ b/src/zcash/util.h @@ -0,0 +1,9 @@ +#ifndef __ZCASH_UTIL_H +#define __ZCASH_UTIL_H + +#include +#include + +std::vector convertIntToVectorLE(const uint64_t val_int); + +#endif // __ZCASH_UTIL_H