Browse Source

`Note` values should be little-endian byte order.

pull/145/head
Sean Bowe 8 years ago
parent
commit
81469bbb83
  1. 6
      src/Makefile.am
  2. 3
      src/Makefile.gtest.include
  3. 78
      src/gtest/test_circuit.cpp
  4. 1
      src/zcash/JoinSplit.cpp
  5. 6
      src/zcash/Note.cpp
  6. 24
      src/zcash/circuit/utils.tcc
  7. 12
      src/zcash/util.cpp
  8. 9
      src/zcash/util.h

6
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)

3
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)

78
src/gtest/test_circuit.cpp

@ -0,0 +1,78 @@
#include <gtest/gtest.h>
#include "uint256.h"
#include "zerocash/utils/util.h"
#include "zcash/util.h"
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/optional.hpp>
#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<typename FieldT>
void test_value_equals(uint64_t i) {
protoboard<FieldT> pb;
pb_variable_array<FieldT> num;
num.allocate(pb, 64, "");
num.fill_with_bits(pb, uint64_to_bool_vector(i));
pb.add_r1cs_constraint(r1cs_constraint<FieldT>(
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<default_r1cs_ppzksnark_pp> FieldT;
test_value_equals<FieldT>(0);
test_value_equals<FieldT>(1);
test_value_equals<FieldT>(3);
test_value_equals<FieldT>(5391);
test_value_equals<FieldT>(883128374);
test_value_equals<FieldT>(173419028459);
test_value_equals<FieldT>(2205843009213693953);
}
TEST(circuit, endianness)
{
std::vector<unsigned char> 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<unsigned char> 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<unsigned char> bad = {0, 1, 2, 3};
ASSERT_THROW(swap_endianness_u64(bad), std::length_error);
}

1
src/zcash/JoinSplit.cpp

@ -3,6 +3,7 @@
#include "sodium.h"
#include "zerocash/utils/util.h"
#include "zcash/util.h"
#include <memory>

6
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<unsigned char> 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);

24
src/zcash/circuit/utils.tcc

@ -29,8 +29,7 @@ std::vector<bool> uint256_to_bool_vector(uint256 input) {
}
std::vector<bool> uint64_to_bool_vector(uint64_t input) {
std::vector<unsigned char> num_bv(8, 0);
libzerocash::convertIntToBytesVector(input, num_bv);
auto num_bv = convertIntToVectorLE(input);
std::vector<bool> num_v(64, 0);
libzerocash::convertBytesVectorToVector(num_bv, num_v);
@ -47,9 +46,26 @@ void insert_uint64(std::vector<bool>& into, uint64_t from) {
into.insert(into.end(), num.begin(), num.end());
}
template<typename T>
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<typename FieldT>
linear_combination<FieldT> packed_addition(pb_variable_array<FieldT>& input) {
linear_combination<FieldT> packed_addition(pb_variable_array<FieldT> input) {
auto input_swapped = swap_endianness_u64(input);
return pb_packing_sum<FieldT>(pb_variable_array<FieldT>(
input.rbegin(), input.rend()
input_swapped.rbegin(), input_swapped.rend()
));
}

12
src/zcash/util.cpp

@ -0,0 +1,12 @@
#include "zcash/util.h"
#include <algorithm>
std::vector<unsigned char> convertIntToVectorLE(const uint64_t val_int) {
std::vector<unsigned char> bytes;
for(size_t i = 0; i < 8; i++) {
bytes.push_back(val_int >> (i * 8));
}
return bytes;
}

9
src/zcash/util.h

@ -0,0 +1,9 @@
#ifndef __ZCASH_UTIL_H
#define __ZCASH_UTIL_H
#include <vector>
#include <cstdint>
std::vector<unsigned char> convertIntToVectorLE(const uint64_t val_int);
#endif // __ZCASH_UTIL_H
Loading…
Cancel
Save