Move libzerocash (dd5db5815be70f0e4895784cc905df6f1c73cb17) into the src tree.

This commit is contained in:
Sean Bowe
2016-02-11 13:44:25 -07:00
parent dba05929e7
commit 523bc77f64
46 changed files with 6641 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
#!/bin/bash
set -eu
SUITE_EXIT_STATUS=0
REPOROOT="$(readlink -f "$(dirname "$0")"/../)"
function run_test_phase
{
echo "===== BEGIN: $*"
set +e
eval "$@"
if [ $? -eq 0 ]
then
echo "===== PASSED: $*"
else
echo "===== FAILED: $*"
SUITE_EXIT_STATUS=1
fi
set -e
}
cd "${REPOROOT}"
# Test phases:
run_test_phase "${REPOROOT}/tests/utilTest"
run_test_phase "${REPOROOT}/tests/zerocashTest"
run_test_phase "${REPOROOT}/tests/merkleTest"
run_test_phase "${REPOROOT}/zerocash_pour_ppzksnark/tests/test_zerocash_pour_ppzksnark"
exit $SUITE_EXIT_STATUS

View File

@@ -0,0 +1,199 @@
/** @file
*****************************************************************************
Test for Merkle tree.
*****************************************************************************
* @author This file is part of libzerocash, developed by the Zerocash
* project and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "libzerocash/IncrementalMerkleTree.h"
#include <iostream>
#include <vector>
#define BOOST_TEST_MODULE merkleTest
#include <boost/test/included/unit_test.hpp>
using namespace libzerocash;
using namespace std;
void constructNonzeroTestVector(std::vector< std::vector<bool> > &values, uint32_t size)
{
values.resize(0);
std::vector<bool> dummy;
dummy.resize(256);
dummy[0] = true;
for (uint32_t i = 0; i < size; i++)
{
values.push_back(dummy);
}
}
void constructZeroTestVector(std::vector< std::vector<bool> > &values, uint32_t size)
{
values.resize(0);
std::vector<bool> dummy;
dummy.resize(256);
for (uint32_t i = 0; i < size; i++)
{
values.push_back(dummy);
}
}
BOOST_AUTO_TEST_CASE( testRootOfTreeOfZerosIsZero ) {
IncrementalMerkleTree incTree;
std::vector< std::vector<bool> > values;
std::vector<bool> actual_root;
constructZeroTestVector(values, 2);
// Create an IncrementalMerkleTree over the values.
if (incTree.insertVector(values) == false) {
BOOST_ERROR("Could not insert into the tree.");
}
incTree.prune();
incTree.getRootValue(actual_root);
std::vector<bool> expected_root(32*8, 0);
BOOST_CHECK( expected_root == actual_root );
}
void add_values_to_reference(IncrementalMerkleTree &tree, std::vector< std::vector<bool> > &values) {
IncrementalMerkleTree newtree(20);
if (newtree.insertVector(values) == false) {
BOOST_ERROR("Could not insert into the tree.");
}
tree.setTo(newtree);
}
BOOST_AUTO_TEST_CASE( test_add_values_to_reference ) {
IncrementalMerkleTree incTree(20);
IncrementalMerkleTree incTree2(20);
std::vector< std::vector<bool> > values;
constructNonzeroTestVector(values, 2);
if (incTree.insertVector(values) == false) {
BOOST_ERROR("Could not insert into the tree.");
}
add_values_to_reference(incTree2, values);
{
std::vector<bool> root1, root2;
incTree.getRootValue(root1);
incTree2.getRootValue(root2);
BOOST_CHECK(root1 == root2);
}
}
BOOST_AUTO_TEST_CASE( testRootOfTreeOfNonZeroIsNonZero ) {
IncrementalMerkleTree incTree;
std::vector< std::vector<bool> > values;
std::vector<bool> actual_root;
constructNonzeroTestVector(values, 2);
// Create an IncrementalMerkleTree over the values.
if (incTree.insertVector(values) == false) {
BOOST_ERROR("Could not insert into the tree.");
}
incTree.prune();
incTree.getRootValue(actual_root);
std::vector<bool> expected_root(32*8, 0);
BOOST_CHECK( expected_root != actual_root );
}
BOOST_AUTO_TEST_CASE( testSerializationEdgeCase ) {
}
BOOST_AUTO_TEST_CASE( testCompactRepresentation ) {
for (uint32_t num_entries = 0; num_entries < 100; num_entries++) {
size_t test_depth = 64;
if (num_entries == 2) {
// This is a particular failure I'm testing with weird
// padding caused by this depth.
test_depth = 20;
}
std::vector< std::vector<bool> > values;
std::vector<bool> root1, root2;
IncrementalMerkleTree incTree(test_depth);
constructNonzeroTestVector(values, num_entries);
BOOST_REQUIRE( incTree.insertVector(values) );
BOOST_REQUIRE( incTree.prune() );
IncrementalMerkleTreeCompact compact = incTree.getCompactRepresentation();
BOOST_REQUIRE( compact.getTreeHeight() == test_depth );
// Calculate what the path to the next-added element should be.
std::vector<unsigned char> path_bytes(8);
std::vector<bool> path_bits;
libzerocash::convertIntToBytesVector(num_entries, path_bytes);
libzerocash::convertBytesVectorToVector(path_bytes, path_bits);
if (test_depth == 64) {
// Make sure the paths match.
BOOST_REQUIRE( compact.getHashList() == path_bits );
}
// Make sure there's a hash for every '1' bit down the path.
BOOST_REQUIRE( compact.getHashVec().size() == libzerocash::countOnes(path_bits) );
/* Test serializing and deserializing. */
std::vector<unsigned char> serializedCompact = compact.serialize();
IncrementalMerkleTreeCompact deserializedCompact = IncrementalMerkleTreeCompact::deserialize(serializedCompact);
BOOST_REQUIRE(compact.getTreeHeight() == deserializedCompact.getTreeHeight());
BOOST_REQUIRE(compact.getHashList() == deserializedCompact.getHashList());
BOOST_REQUIRE(compact.getHashVec() == deserializedCompact.getHashVec());
// Make sure 'restoring' the tree results in the same root.
IncrementalMerkleTree newTree(compact);
incTree.getRootValue(root1);
incTree.getRootValue(root2);
BOOST_REQUIRE( root1 == root2 );
}
}
BOOST_AUTO_TEST_CASE( testCompactDeserializationFailures ) {
IncrementalMerkleTree incTree(64);
std::vector< std::vector<bool> > values;
constructNonzeroTestVector(values, 5);
BOOST_REQUIRE( incTree.insertVector(values) );
BOOST_REQUIRE( incTree.prune() );
IncrementalMerkleTreeCompact compact = incTree.getCompactRepresentation();
/* Base the following tests off of this valid serialization. */
std::vector<unsigned char> serialized = compact.serialize();
/* Should fail if we truncate any number of bytes off the end. */
for (size_t trunc_len = 0; trunc_len < serialized.size(); trunc_len++) {
std::vector<unsigned char> truncated(serialized.begin(), serialized.begin() + trunc_len);
BOOST_CHECK_THROW(
IncrementalMerkleTreeCompact::deserialize(truncated),
std::out_of_range
);
}
/* Should fail if we append any number of extra bytes on the end. */
std::vector<unsigned char> extra_byte = serialized;
extra_byte.push_back(0x00);
BOOST_CHECK_THROW(
IncrementalMerkleTreeCompact::deserialize(extra_byte),
std::runtime_error
);
}

View File

@@ -0,0 +1,48 @@
/** @file
*****************************************************************************
Implementation of interfaces for a timer to profile executions.
*****************************************************************************
* @author This file is part of libzerocash, developed by the Zerocash
* project and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include <stdio.h>
#include <sys/time.h>
#include "tests/timer.h"
namespace libzerocash {
struct timeval tv_start;
struct timeval tv_end;
void timer_start() {
printf("%s\n", "Starting Timer");
gettimeofday(&tv_start, 0);
}
void timer_stop() {
float elapsed;
gettimeofday(&tv_end, 0);
elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000);
printf("%s [%fs]\n\n", "Stopping Timer", elapsed);
}
void timer_start(const std::string location) {
printf("%s %s\n", "(enter)", location.c_str());
gettimeofday(&tv_start, 0);
}
void timer_stop(const std::string location) {
float elapsed;
gettimeofday(&tv_end, 0);
elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000);
printf("%s %s [%fs]\n\n", "(leave)", location.c_str(), elapsed);
}
} /* namespace libzerocash */

View File

@@ -0,0 +1,28 @@
/** @file
*****************************************************************************
Declaration of interfaces for a timer to profile executions.
*****************************************************************************
* @author This file is part of libzerocash, developed by the Zerocash
* project and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef TIMER_H_
#define TIMER_H_
#include <string>
namespace libzerocash {
void timer_start();
void timer_stop();
void timer_start(const std::string location);
void timer_stop(const std::string location);
} /* namespace libzerocash */
#endif /* TIMER_H_ */

View File

@@ -0,0 +1,534 @@
#define BOOST_TEST_MODULE utilTest
#include <boost/test/included/unit_test.hpp>
#include "libzerocash/utils/util.h"
#include "libzerocash/utils/sha256.h"
#define SHA256_PREIMAGE_BYTES 3
const unsigned char sha256_preimage[SHA256_PREIMAGE_BYTES] = { 'a', 'b', 'c' };
/* This is the SHA256 hash of "abc" according to the modified implementation of
* SHA256 included in libzerocash. */
const unsigned char sha256_hash[32] = { 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae,
0x85, 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f,
0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f, 0x9b,
0x05, 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab,
0x5b, 0xe0, 0xcd, 0x19 };
BOOST_AUTO_TEST_CASE( testGetRandBytes ) {
unsigned char bytes1[32];
unsigned char bytes2[32];
memset(bytes1, 0, 32);
memset(bytes2, 0, 32);
libzerocash::getRandBytes(bytes1, 32);
libzerocash::getRandBytes(bytes2, 32);
BOOST_CHECK( memcmp(bytes1, bytes2, 32) != 0 );
BOOST_CHECK( memcmp(bytes1, bytes1+16, 16) != 0 );
}
BOOST_AUTO_TEST_CASE( testConvertVectorToInt ) {
BOOST_CHECK(libzerocash::convertVectorToInt({0}) == 0);
BOOST_CHECK(libzerocash::convertVectorToInt({1}) == 1);
BOOST_CHECK(libzerocash::convertVectorToInt({0,1}) == 1);
BOOST_CHECK(libzerocash::convertVectorToInt({1,0}) == 2);
BOOST_CHECK(libzerocash::convertVectorToInt({1,1}) == 3);
BOOST_CHECK(libzerocash::convertVectorToInt({1,0,0}) == 4);
BOOST_CHECK(libzerocash::convertVectorToInt({1,0,1}) == 5);
BOOST_CHECK(libzerocash::convertVectorToInt({1,1,0}) == 6);
BOOST_CHECK_THROW(libzerocash::convertVectorToInt(std::vector<bool>(100)), std::length_error);
{
std::vector<bool> v(63, 1);
BOOST_CHECK(libzerocash::convertVectorToInt(v) == 0x7fffffffffffffff);
}
{
std::vector<bool> v(64, 1);
BOOST_CHECK(libzerocash::convertVectorToInt(v) == 0xffffffffffffffff);
}
}
BOOST_AUTO_TEST_CASE( testConvertBytesToVector ) {
unsigned char bytes[5] = {0x00, 0x01, 0x03, 0x12, 0xFF};
std::vector<bool> v1(5*8);
libzerocash::convertBytesToVector(bytes, v1);
std::vector<bool> v2 = {
// 0x00
0, 0, 0, 0, 0, 0, 0, 0,
// 0x01
0, 0, 0, 0, 0, 0, 0, 1,
// 0x03
0, 0, 0, 0, 0, 0, 1, 1,
// 0x12
0, 0, 0, 1, 0, 0, 1, 0,
// 0xFF
1, 1, 1, 1, 1, 1, 1, 1
};
BOOST_CHECK(v1 == v2);
std::vector<bool> unevensize(4);
unsigned char abyte[1] = { 0x55 };
libzerocash::convertBytesToVector(abyte, unevensize);
/* This may not be what we would expect, but this test will alert us if the
* behavior changes. */
v2 = { 0, 0, 0, 0 };
BOOST_CHECK(unevensize == v2);
}
BOOST_AUTO_TEST_CASE( testConvertVectorToBytes) {
unsigned char bytes[5] = {0x00, 0x01, 0x03, 0x12, 0xFF};
std::vector<bool> v = {
// 0x00
0, 0, 0, 0, 0, 0, 0, 0,
// 0x01
0, 0, 0, 0, 0, 0, 0, 1,
// 0x03
0, 0, 0, 0, 0, 0, 1, 1,
// 0x12
0, 0, 0, 1, 0, 0, 1, 0,
// 0xFF
1, 1, 1, 1, 1, 1, 1, 1
};
unsigned char output[5];
libzerocash::convertVectorToBytes(v, output);
BOOST_CHECK( memcmp(bytes, output, sizeof(bytes)) == 0 );
/* This is not necessarily the behavior one would expect, but this test will
* notify us if it changes. */
unsigned char onebyte[1];
std::vector<bool> unevensize { 1, 1, 1, 1, 1, 1, 1 };
libzerocash::convertVectorToBytes(unevensize, onebyte);
BOOST_CHECK(onebyte[0] == 0);
}
BOOST_AUTO_TEST_CASE( testConvertBytesToBytesVector ) {
unsigned char bytes[16];
for (int i = 0; i < 16; i++) {
bytes[i] = i;
}
std::vector<unsigned char> v(16);
libzerocash::convertBytesToBytesVector(bytes, v);
for (int i = 0; i < 16; i++) {
BOOST_CHECK(v.at(i) == bytes[i]);
}
}
BOOST_AUTO_TEST_CASE( testConvertBytesVectorToBytes ) {
std::vector<unsigned char>v(16);
for (int i = 0; i < 16; i++) {
v[i] = i;
}
unsigned char bytes[16];
memset(bytes, 0, 16);
libzerocash::convertBytesVectorToBytes(v, bytes);
for (int i = 0; i < 16; i++) {
BOOST_CHECK(bytes[i] == v.at(i));
}
}
BOOST_AUTO_TEST_CASE( testConvertBytesVectorToVector ) {
std::vector<unsigned char> bytes = {0x00, 0x01, 0x03, 0x12, 0xFF};
std::vector<bool> expected_bits = {
// 0x00
0, 0, 0, 0, 0, 0, 0, 0,
// 0x01
0, 0, 0, 0, 0, 0, 0, 1,
// 0x03
0, 0, 0, 0, 0, 0, 1, 1,
// 0x12
0, 0, 0, 1, 0, 0, 1, 0,
// 0xFF
1, 1, 1, 1, 1, 1, 1, 1
};
std::vector<bool> actual_bits;
libzerocash::convertBytesVectorToVector(bytes, actual_bits);
BOOST_CHECK(actual_bits == expected_bits);
}
BOOST_AUTO_TEST_CASE( testConvertVectorToBytesVector ) {
std::vector<unsigned char> expected_bytes = {0x00, 0x01, 0x03, 0x12, 0xFF};
std::vector<bool> bits = {
// 0x00
0, 0, 0, 0, 0, 0, 0, 0,
// 0x01
0, 0, 0, 0, 0, 0, 0, 1,
// 0x03
0, 0, 0, 0, 0, 0, 1, 1,
// 0x12
0, 0, 0, 1, 0, 0, 1, 0,
// 0xFF
1, 1, 1, 1, 1, 1, 1, 1
};
// TODO: evaluate whether initializing with 5 should be necessary.
std::vector<unsigned char> actual_bytes(5);
libzerocash::convertVectorToBytesVector(bits, actual_bytes);
BOOST_CHECK(actual_bytes == expected_bytes);
}
BOOST_AUTO_TEST_CASE( testConvertIntToBytesVector ) {
uint64_t val;
std::vector<unsigned char> expected;
std::vector<unsigned char> bytes(8);
val = 0ULL;
expected = { 0, 0, 0, 0, 0, 0, 0, 0 };
libzerocash::convertIntToBytesVector(val, bytes);
BOOST_CHECK( expected == bytes );
val = 1ULL;
expected = { 0, 0, 0, 0, 0, 0, 0, 1 };
libzerocash::convertIntToBytesVector(val, bytes);
BOOST_CHECK( expected == bytes );
val = 0xffffffffffffffffULL;
expected = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
libzerocash::convertIntToBytesVector(val, bytes);
BOOST_CHECK( expected == bytes );
val = 0x8000000080000001ULL; // sign extension
expected = { 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01 };
libzerocash::convertIntToBytesVector(val, bytes);
BOOST_CHECK( expected == bytes );
// The following two tests aren't necessarily desired results. They merely
// document the behavior so that we'll be alerted if it changes in the
// future.
val = 0xffffffffdeadbeefULL; // truncation
expected = { 0xde, 0xad, 0xbe, 0xef };
std::vector<unsigned char> small_bytes(4);
libzerocash::convertIntToBytesVector(val, small_bytes);
BOOST_CHECK( expected == small_bytes );
val = 0xf1f2f3f401020304ULL; // bytes buffer is too big
// The first byte is 4 because `>> 64` is undefined, and that's the result
// it has on my system (note that it's the same as the original LSB).
expected = { 0x04, 0xf1, 0xf2, 0xf3, 0xf4, 0x01, 0x02, 0x03, 0x04 };
std::vector<unsigned char> big_bytes(9);
libzerocash::convertIntToBytesVector(val, big_bytes);
BOOST_CHECK( expected == big_bytes);
}
BOOST_AUTO_TEST_CASE( testConvertBytesVectorToInt ) {
uint64_t val;
uint64_t expected;
std::vector<unsigned char> bytes;
bytes = { 0, 0, 0, 0, 0, 0, 0, 0 };
expected = 0ULL;
val = libzerocash::convertBytesVectorToInt(bytes);
BOOST_CHECK( expected == val );
bytes = { 0, 0, 0, 0, 0, 0, 0, 1 };
expected = 1ULL;
val = libzerocash::convertBytesVectorToInt(bytes);
BOOST_CHECK( expected == val );
bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
expected = 0xffffffffffffffffULL;
val = libzerocash::convertBytesVectorToInt(bytes);
BOOST_CHECK( expected == val );
bytes = { 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01 };
expected = 0x8000000080000001ULL;
val = libzerocash::convertBytesVectorToInt(bytes);
BOOST_CHECK( expected == val );
bytes = { 0xde, 0xad, 0xbe, 0xef }; // opposite of truncation
expected = 0xdeadbeefULL;
val = libzerocash::convertBytesVectorToInt(bytes);
BOOST_CHECK( expected == val );
}
BOOST_AUTO_TEST_CASE( testConvertIntToVector ) {
uint64_t val;
std::vector<bool> expected;
std::vector<bool> vector;
val = 0ULL;
expected = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
libzerocash::convertIntToVector(val, vector);
BOOST_CHECK( expected == vector );
val = 1ULL;
expected = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 };
libzerocash::convertIntToVector(val, vector);
BOOST_CHECK( expected == vector );
val = 0xffffffffffffffffULL;
expected = { 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1 };
libzerocash::convertIntToVector(val, vector);
BOOST_CHECK( expected == vector );
val = 0x8000000080000001ULL; // sign extension
expected = { 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1 };
libzerocash::convertIntToVector(val, vector);
BOOST_CHECK( expected == vector );
std::vector<bool> too_big(100);
libzerocash::convertIntToVector(0, too_big);
BOOST_CHECK(too_big.size() == 64);
std::vector<bool> too_small(10);
libzerocash::convertIntToVector(0, too_small);
BOOST_CHECK(too_big.size() == 64);
}
BOOST_AUTO_TEST_CASE( testConcatenateTwoBoolVectors ) {
std::vector<bool> front = { 0, 1, 0 };
std::vector<bool> back = { 1, 0, 1 };
std::vector<bool> expected = { 0, 1, 0, 1, 0, 1 };
std::vector<bool> actual;
libzerocash::concatenateVectors(front, back, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testConcatenateTwoByteVectors ) {
std::vector<unsigned char> front = { 0, 1, 2 };
std::vector<unsigned char> back = { 3, 4, 5 };
std::vector<unsigned char> expected = { 0, 1, 2, 3, 4, 5 };
std::vector<unsigned char> actual;
libzerocash::concatenateVectors(front, back, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testConcatenateThreeBoolVectors ) {
std::vector<bool> front = { 0, 1, 0 };
std::vector<bool> middle { 1, 1, 1 };
std::vector<bool> back = { 1, 0, 1 };
std::vector<bool> expected = { 0, 1, 0, 1, 1, 1, 1, 0, 1 };
std::vector<bool> actual;
libzerocash::concatenateVectors(front, middle, back, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testConcatenateThreeByteVectors ) {
std::vector<unsigned char> front = { 0, 1, 0 };
std::vector<unsigned char> middle { 1, 1, 1 };
std::vector<unsigned char> back = { 1, 0, 1 };
std::vector<unsigned char> expected = { 0, 1, 0, 1, 1, 1, 1, 0, 1 };
std::vector<unsigned char> actual;
libzerocash::concatenateVectors(front, middle, back, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testSHA256ModifiedTestVectors ) {
unsigned char actual_hash[32];
libzerocash::sha256(sha256_preimage, actual_hash, 3);
BOOST_CHECK( memcmp(sha256_hash, actual_hash, 32) == 0 );
}
BOOST_AUTO_TEST_CASE( testSHA256ModifiedTestVectorsCTX ) {
unsigned char actual_hash[32];
SHA256_CTX_mod ctx256;
libzerocash::sha256(&ctx256, sha256_preimage, actual_hash, 3);
BOOST_CHECK( memcmp(sha256_hash, actual_hash, 32) == 0 );
}
BOOST_AUTO_TEST_CASE( testSHA256TestVectors ) {
/* Tests an actual SHA256 test vector (with length padding) to make sure
* libzerocash's implementation is actually the same as SHA256 with the
* length padding removed. */
unsigned char preimage[3] = { 'a', 'b', 'c' };
unsigned char expected_hash[32] = { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01,
0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03,
0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00,
0x15, 0xad };
unsigned char actual_hash[32];
SHA256_CTX_mod ctx256;
sha256_init(&ctx256);
sha256_update(&ctx256, preimage, 3);
sha256_length_padding(&ctx256);
sha256_final_no_padding(&ctx256, actual_hash);
BOOST_CHECK( memcmp(expected_hash, actual_hash, 32) == 0 );
}
BOOST_AUTO_TEST_CASE( testHashBoolVectorToBoolVectorCTX ) {
SHA256_CTX_mod ctx256;
std::vector<bool> preimage(SHA256_PREIMAGE_BYTES * 8);
libzerocash::convertBytesToVector(sha256_preimage, preimage);
std::vector<bool> expected(32*8);
libzerocash::convertBytesToVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<bool> actual(32*8);
libzerocash::hashVector(&ctx256, preimage, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testHashByteVectorToByteVectorCTX ) {
SHA256_CTX_mod ctx256;
std::vector<unsigned char> preimage(SHA256_PREIMAGE_BYTES);
libzerocash::convertBytesToBytesVector(sha256_preimage, preimage);
std::vector<unsigned char> expected(32);
libzerocash::convertBytesToBytesVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<unsigned char> actual(32);
libzerocash::hashVector(&ctx256, preimage, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testHashBoolVectorToBoolVector ) {
std::vector<bool> preimage(SHA256_PREIMAGE_BYTES * 8);
libzerocash::convertBytesToVector(sha256_preimage, preimage);
std::vector<bool> expected(32*8);
libzerocash::convertBytesToVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<bool> actual(32*8);
libzerocash::hashVector(preimage, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testHashByteVectorToByteVector ) {
std::vector<unsigned char> preimage(SHA256_PREIMAGE_BYTES);
libzerocash::convertBytesToBytesVector(sha256_preimage, preimage);
std::vector<unsigned char> expected(32);
libzerocash::convertBytesToBytesVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<unsigned char> actual(32);
libzerocash::hashVector(preimage, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testHashBoolVectorsCTX ) {
SHA256_CTX_mod ctx256;
std::vector<bool> preimage1(8);
libzerocash::convertBytesToVector(sha256_preimage, preimage1);
std::vector<bool> preimage2((SHA256_PREIMAGE_BYTES - 1) * 8);
libzerocash::convertBytesToVector(sha256_preimage + 1, preimage2);
std::vector<bool> expected(32*8);
libzerocash::convertBytesToVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<bool> actual(32 * 8);
libzerocash::hashVectors(&ctx256, preimage1, preimage2, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testHashByteVectorsCTX ) {
SHA256_CTX_mod ctx256;
std::vector<unsigned char> preimage1(1);
libzerocash::convertBytesToBytesVector(sha256_preimage, preimage1);
std::vector<unsigned char> preimage2(SHA256_PREIMAGE_BYTES - 1);
libzerocash::convertBytesToBytesVector(sha256_preimage + 1, preimage2);
std::vector<unsigned char> expected(32);
libzerocash::convertBytesToBytesVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<unsigned char> actual(32);
libzerocash::hashVectors(&ctx256, preimage1, preimage2, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testHashBoolVectors ) {
std::vector<bool> preimage1(8);
libzerocash::convertBytesToVector(sha256_preimage, preimage1);
std::vector<bool> preimage2((SHA256_PREIMAGE_BYTES - 1) * 8);
libzerocash::convertBytesToVector(sha256_preimage + 1, preimage2);
std::vector<bool> expected(32*8);
libzerocash::convertBytesToVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<bool> actual(32 * 8);
libzerocash::hashVectors(preimage1, preimage2, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testHashByteVectors ) {
std::vector<unsigned char> preimage1(1);
libzerocash::convertBytesToBytesVector(sha256_preimage, preimage1);
std::vector<unsigned char> preimage2(SHA256_PREIMAGE_BYTES - 1);
libzerocash::convertBytesToBytesVector(sha256_preimage + 1, preimage2);
std::vector<unsigned char> expected(32);
libzerocash::convertBytesToBytesVector(sha256_hash, expected);
// TODO: evaluate whether this should be a necessary precondition.
std::vector<unsigned char> actual(32);
libzerocash::hashVectors(preimage1, preimage2, actual);
BOOST_CHECK( expected == actual );
}
BOOST_AUTO_TEST_CASE( testVectorIsZero ) {
std::vector<bool> bits;
BOOST_CHECK( libzerocash::VectorIsZero(bits) );
bits = { 0 };
BOOST_CHECK( libzerocash::VectorIsZero(bits) );
bits = { 0, 0 };
BOOST_CHECK( libzerocash::VectorIsZero(bits) );
bits = { 1 };
BOOST_CHECK( !libzerocash::VectorIsZero(bits) );
bits = { 0, 1 };
BOOST_CHECK( !libzerocash::VectorIsZero(bits) );
}

View File

@@ -0,0 +1,634 @@
/** @file
*****************************************************************************
A test for Zerocash.
*****************************************************************************
* @author This file is part of libzerocash, developed by the Zerocash
* project and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include <stdlib.h>
#include <iostream>
#define BOOST_TEST_MODULE zerocashTest
#include <boost/test/included/unit_test.hpp>
#include "timer.h"
#include "libzerocash/Zerocash.h"
#include "libzerocash/ZerocashParams.h"
#include "libzerocash/Address.h"
#include "libzerocash/CoinCommitment.h"
#include "libzerocash/Coin.h"
#include "libzerocash/IncrementalMerkleTree.h"
#include "libzerocash/MintTransaction.h"
#include "libzerocash/PourTransaction.h"
#include "libzerocash/PourInput.h"
#include "libzerocash/PourOutput.h"
#include "libzerocash/utils/util.h"
using namespace std;
using namespace libsnark;
#define TEST_TREE_DEPTH 4
BOOST_AUTO_TEST_CASE( SaveAndLoadKeysFromFiles ) {
cout << "\nSaveAndLoadKeysFromFiles TEST\n" << endl;
cout << "Creating Params...\n" << endl;
libzerocash::timer_start("Param Generation");
auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH);
libzerocash::ZerocashParams p(
TEST_TREE_DEPTH,
&keypair
);
libzerocash::timer_stop("Param Generation");
print_mem("after param generation");
cout << "Successfully created Params.\n" << endl;
std::string vk_path = "./zerocashTest-verification-key";
std::string pk_path = "./zerocashTest-proving-key";
libzerocash::timer_start("Saving Proving Key");
libzerocash::ZerocashParams::SaveProvingKeyToFile(
&p.getProvingKey(),
pk_path
);
libzerocash::timer_stop("Saving Proving Key");
libzerocash::timer_start("Saving Verification Key");
libzerocash::ZerocashParams::SaveVerificationKeyToFile(
&p.getVerificationKey(),
vk_path
);
libzerocash::timer_stop("Saving Verification Key");
libzerocash::timer_start("Loading Proving Key");
auto pk_loaded = libzerocash::ZerocashParams::LoadProvingKeyFromFile(pk_path, TEST_TREE_DEPTH);
libzerocash::timer_stop("Loading Proving Key");
libzerocash::timer_start("Loading Verification Key");
auto vk_loaded = libzerocash::ZerocashParams::LoadVerificationKeyFromFile(vk_path, TEST_TREE_DEPTH);
libzerocash::timer_stop("Loading Verification Key");
cout << "Comparing Proving and Verification key.\n" << endl;
if ( !( p.getProvingKey() == pk_loaded && p.getVerificationKey() == vk_loaded) ) {
BOOST_ERROR("Proving and verification key are not equal.");
}
vector<libzerocash::Coin> coins;
vector<libzerocash::Address> addrs;
cout << "Creating Addresses and Coins...\n" << endl;
for(size_t i = 0; i < 5; i++) {
addrs.push_back(libzerocash::Address::CreateNewRandomAddress());
coins.push_back(libzerocash::Coin(addrs.at(i).getPublicAddress(), i));
}
cout << "Successfully created address and coins.\n" << endl;
cout << "Creating a Mint Transaction...\n" << endl;
libzerocash::MintTransaction minttx(coins.at(0));
cout << "Successfully created a Mint Transaction.\n" << endl;
vector<std::vector<bool>> coinValues(5);
vector<bool> temp_comVal(ZC_CM_SIZE * 8);
for(size_t i = 0; i < coinValues.size(); i++) {
libzerocash::convertBytesVectorToVector(coins.at(i).getCoinCommitment().getCommitmentValue(), temp_comVal);
coinValues.at(i) = temp_comVal;
}
cout << "Creating Merkle Tree...\n" << endl;
libzerocash::IncrementalMerkleTree merkleTree(coinValues, TEST_TREE_DEPTH);
cout << "Successfully created Merkle Tree.\n" << endl;
std::vector<bool> index;
cout << "Creating Witness 1...\n" << endl;
merkle_authentication_path witness_1(TEST_TREE_DEPTH);
libzerocash::convertIntToVector(1, index);
merkleTree.getWitness(index, witness_1);
cout << "Successfully created Witness 1.\n" << endl;
cout << "Creating Witness 2...\n" << endl;
merkle_authentication_path witness_2(TEST_TREE_DEPTH);
libzerocash::convertIntToVector(3, index);
merkleTree.getWitness(index, witness_2);
cout << "Successfully created Witness 2.\n" << endl;
cout << "Creating coins to spend...\n" << endl;
libzerocash::Address newAddress3 = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress3 = newAddress3.getPublicAddress();
libzerocash::Address newAddress4 = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress4 = newAddress4.getPublicAddress();
libzerocash::Coin c_1_new(pubAddress3, 2);
libzerocash::Coin c_2_new(pubAddress4, 2);
cout << "Successfully created coins to spend.\n" << endl;
vector<unsigned char> rt(ZC_ROOT_SIZE);
merkleTree.getRootValue(rt);
// XXX: debugging
std::cout << "Root: " << rt.size() << endl;
std::cout << "wit1: " << witness_1.size() << endl;
std::cout << "wit2: " << witness_1.size() << endl;
vector<unsigned char> as(ZC_SIG_PK_SIZE, 'a');
cout << "Creating a pour transaction...\n" << endl;
libzerocash::PourTransaction pourtx(1, p,
rt,
coins.at(1), coins.at(3),
addrs.at(1), addrs.at(3),
1, 3,
witness_1, witness_2,
pubAddress3, pubAddress4,
0,
0,
as,
c_1_new, c_2_new);
cout << "Successfully created a pour transaction.\n" << endl;
std::vector<unsigned char> pubkeyHash(ZC_SIG_PK_SIZE, 'a');
cout << "Verifying a pour transaction...\n" << endl;
bool pourtx_res = pourtx.verify(p, pubkeyHash, rt);
BOOST_CHECK(pourtx_res);
}
BOOST_AUTO_TEST_CASE( PourInputOutputTest ) {
// dummy input
{
libzerocash::PourInput input(TEST_TREE_DEPTH);
BOOST_CHECK(input.old_coin.getValue() == 0);
BOOST_CHECK(input.old_address.getPublicAddress() == input.old_coin.getPublicAddress());
}
// dummy output
{
libzerocash::PourOutput output(0);
BOOST_CHECK(output.new_coin.getValue() == 0);
BOOST_CHECK(output.to_address == output.new_coin.getPublicAddress());
}
}
// testing with general situational setup
bool test_pour(libzerocash::ZerocashParams& p,
uint64_t vpub_in,
uint64_t vpub_out,
std::vector<uint64_t> inputs, // values of the inputs (max 2)
std::vector<uint64_t> outputs) // values of the outputs (max 2)
{
using pour_input_state = std::tuple<libzerocash::Address, libzerocash::Coin, std::vector<bool>>;
// Construct incremental merkle tree
libzerocash::IncrementalMerkleTree merkleTree(TEST_TREE_DEPTH);
// Dummy sig_pk
vector<unsigned char> as(ZC_SIG_PK_SIZE, 'a');
vector<libzerocash::PourInput> pour_inputs;
vector<libzerocash::PourOutput> pour_outputs;
vector<pour_input_state> input_state;
for(std::vector<uint64_t>::iterator it = inputs.begin(); it != inputs.end(); ++it) {
libzerocash::Address addr = libzerocash::Address::CreateNewRandomAddress();
libzerocash::Coin coin(addr.getPublicAddress(), *it);
// commitment from coin
std::vector<bool> commitment(ZC_CM_SIZE * 8);
libzerocash::convertBytesVectorToVector(coin.getCoinCommitment().getCommitmentValue(), commitment);
// insert commitment into the merkle tree
std::vector<bool> index;
merkleTree.insertElement(commitment, index);
// store the state temporarily
input_state.push_back(std::make_tuple(addr, coin, index));
}
// compute the merkle root we will be working with
vector<unsigned char> rt(ZC_ROOT_SIZE);
{
vector<bool> root_bv(ZC_ROOT_SIZE * 8);
merkleTree.getRootValue(root_bv);
libzerocash::convertVectorToBytesVector(root_bv, rt);
}
// get witnesses for all the input coins and construct the pours
for(vector<pour_input_state>::iterator it = input_state.begin(); it != input_state.end(); ++it) {
merkle_authentication_path path(TEST_TREE_DEPTH);
auto index = std::get<2>(*it);
merkleTree.getWitness(index, path);
pour_inputs.push_back(libzerocash::PourInput(std::get<1>(*it), std::get<0>(*it), libzerocash::convertVectorToInt(index), path));
}
// construct dummy outputs with the given values
for(vector<uint64_t>::iterator it = outputs.begin(); it != outputs.end(); ++it) {
pour_outputs.push_back(libzerocash::PourOutput(*it));
}
libzerocash::PourTransaction pourtx(p, as, rt, pour_inputs, pour_outputs, vpub_in, vpub_out);
BOOST_CHECK(pourtx.verify(p, as, rt));
}
BOOST_AUTO_TEST_CASE( PourVpubInTest ) {
auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH);
libzerocash::ZerocashParams p(
TEST_TREE_DEPTH,
&keypair
);
// Things that should work..
BOOST_CHECK(test_pour(p, 0, 0, {1}, {1}));
BOOST_CHECK(test_pour(p, 0, 0, {2}, {1, 1}));
BOOST_CHECK(test_pour(p, 0, 0, {2, 2}, {3, 1}));
BOOST_CHECK(test_pour(p, 0, 1, {1}, {}));
BOOST_CHECK(test_pour(p, 0, 1, {2}, {1}));
BOOST_CHECK(test_pour(p, 0, 1, {2, 2}, {2, 1}));
BOOST_CHECK(test_pour(p, 1, 0, {}, {1}));
BOOST_CHECK(test_pour(p, 1, 0, {1}, {1, 1}));
BOOST_CHECK(test_pour(p, 1, 0, {2, 2}, {2, 3}));
// Things that should not work...
BOOST_CHECK_THROW(test_pour(p, 0, 1, {1}, {1}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 0, 1, {2}, {1, 1}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 0, 1, {2, 2}, {3, 1}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 0, 2, {1}, {}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 0, 2, {2}, {1}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 0, 2, {2, 2}, {2, 1}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 1, 1, {}, {1}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 1, 1, {1}, {1, 1}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 1, 1, {2, 2}, {2, 3}), std::invalid_argument);
BOOST_CHECK_THROW(test_pour(p, 0, 0, {2, 2}, {2, 3}), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE( CoinTest ) {
cout << "\nCOIN TEST\n" << endl;
libzerocash::Address newAddress = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress = newAddress.getPublicAddress();
libzerocash::Coin coin(pubAddress, 0);
cout << "Successfully created a coin.\n" << endl;
///////////////////////////////////////////////////////////////////////////
libzerocash::timer_start("Coin");
libzerocash::Coin coin2(pubAddress, 0);
libzerocash::timer_stop("Coin");
cout << "Successfully created a coin.\n" << endl;
}
BOOST_AUTO_TEST_CASE( MintTxTest ) {
cout << "\nMINT TRANSACTION TEST\n" << endl;
libzerocash::Address newAddress = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress = newAddress.getPublicAddress();
vector<unsigned char> value(ZC_V_SIZE, 0);
libzerocash::timer_start("Coin");
const libzerocash::Coin coin(pubAddress, 0);
libzerocash::timer_stop("Coin");
libzerocash::timer_start("Mint Transaction");
libzerocash::MintTransaction minttx(coin);
libzerocash::timer_stop("Mint Transaction");
cout << "Successfully created a mint transaction.\n" << endl;
libzerocash::timer_start("Mint Transaction Verify");
bool minttx_res = minttx.verify();
libzerocash::timer_stop("Mint Transaction Verify");
BOOST_CHECK(minttx_res);
}
BOOST_AUTO_TEST_CASE( PourTxTest ) {
cout << "\nPOUR TRANSACTION TEST\n" << endl;
cout << "Creating Params...\n" << endl;
libzerocash::timer_start("Param Generation");
auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH);
libzerocash::ZerocashParams p(
TEST_TREE_DEPTH,
&keypair
);
libzerocash::timer_stop("Param Generation");
print_mem("after param generation");
cout << "Successfully created Params.\n" << endl;
vector<libzerocash::Coin> coins;
vector<libzerocash::Address> addrs;
for(size_t i = 0; i < 5; i++) {
addrs.push_back(libzerocash::Address::CreateNewRandomAddress());
coins.push_back(libzerocash::Coin(addrs.at(i).getPublicAddress(), i));
}
cout << "Successfully created coins.\n" << endl;
vector<std::vector<bool>> coinValues(5);
vector<bool> temp_comVal(ZC_CM_SIZE * 8);
for(size_t i = 0; i < coinValues.size(); i++) {
libzerocash::convertBytesVectorToVector(coins.at(i).getCoinCommitment().getCommitmentValue(), temp_comVal);
coinValues.at(i) = temp_comVal;
libzerocash::printVectorAsHex("Coin => ", coinValues.at(i));
}
cout << "Creating Merkle Tree...\n" << endl;
libzerocash::timer_start("Merkle Tree");
libzerocash::IncrementalMerkleTree merkleTree(coinValues, TEST_TREE_DEPTH);
libzerocash::timer_stop("Merkle Tree");
cout << "Successfully created Merkle Tree.\n" << endl;
merkle_authentication_path witness_1(TEST_TREE_DEPTH);
libzerocash::timer_start("Witness");
std::vector<bool> index;
libzerocash::convertIntToVector(1, index);
if (merkleTree.getWitness(index, witness_1) == false) {
BOOST_ERROR("Could not get witness");
}
libzerocash::timer_stop("Witness");
cout << "Witness 1: " << endl;
for(size_t i = 0; i < witness_1.size(); i++) {
libzerocash::printVectorAsHex(witness_1.at(i));
}
cout << "\n" << endl;
merkle_authentication_path witness_2(TEST_TREE_DEPTH);
libzerocash::convertIntToVector(3, index);
if (merkleTree.getWitness(index, witness_2) == false) {
cout << "Could not get witness" << endl;
}
cout << "Witness 2: " << endl;
for(size_t i = 0; i < witness_2.size(); i++) {
libzerocash::printVectorAsHex(witness_2.at(i));
}
cout << "\n" << endl;
libzerocash::Address newAddress3 = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress3 = newAddress3.getPublicAddress();
libzerocash::Address newAddress4 = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress4 = newAddress4.getPublicAddress();
libzerocash::Coin c_1_new(pubAddress3, 2);
libzerocash::Coin c_2_new(pubAddress4, 2);
vector<bool> root_bv(ZC_ROOT_SIZE * 8);
merkleTree.getRootValue(root_bv);
vector<unsigned char> rt(ZC_ROOT_SIZE);
libzerocash::convertVectorToBytesVector(root_bv, rt);
vector<unsigned char> ones(ZC_V_SIZE, 1);
vector<unsigned char> twos(ZC_V_SIZE, 2);
vector<unsigned char> as(ZC_SIG_PK_SIZE, 'a');
cout << "Creating a pour transaction...\n" << endl;
libzerocash::timer_start("Pour Transaction");
libzerocash::PourTransaction pourtx(1, p, rt, coins.at(1), coins.at(3), addrs.at(1), addrs.at(3), 1, 3, witness_1, witness_2, pubAddress3, pubAddress4, 0, 0, as, c_1_new, c_2_new);
libzerocash::timer_stop("Pour Transaction");
print_mem("after pour transaction");
cout << "Successfully created a pour transaction.\n" << endl;
std::vector<unsigned char> pubkeyHash(ZC_SIG_PK_SIZE, 'a');
libzerocash::timer_start("Pour Transaction Verify");
bool pourtx_res = pourtx.verify(p, pubkeyHash, rt);
libzerocash::timer_stop("Pour Transaction Verify");
BOOST_CHECK(pourtx_res);
}
BOOST_AUTO_TEST_CASE( MerkleTreeSimpleTest ) {
cout << "\nMERKLE TREE SIMPLE TEST\n" << endl;
vector<libzerocash::Coin> coins;
vector<libzerocash::Address> addrs;
cout << "Creating coins...\n" << endl;
for(size_t i = 0; i < 5; i++) {
addrs.push_back(libzerocash::Address::CreateNewRandomAddress());
coins.push_back(libzerocash::Coin(addrs.at(i).getPublicAddress(), i));
}
cout << "Successfully created coins.\n" << endl;
vector<std::vector<bool>> coinValues(coins.size());
vector<bool> temp_comVal(ZC_CM_SIZE * 8);
for(size_t i = 0; i < coinValues.size(); i++) {
libzerocash::convertBytesVectorToVector(coins.at(i).getCoinCommitment().getCommitmentValue(), temp_comVal);
coinValues.at(i) = temp_comVal;
libzerocash::printVectorAsHex(coinValues.at(i));
}
cout << "Creating Merkle Tree...\n" << endl;
libzerocash::IncrementalMerkleTree merkleTree(64);
vector<bool> root;
merkleTree.getRootValue(root);
cout << "Root: ";
libzerocash::printVectorAsHex(root);
cout << endl;
cout << "Successfully created Merkle Tree.\n" << endl;
cout << "Copying and pruning Merkle Tree...\n" << endl;
libzerocash::IncrementalMerkleTree copyTree = merkleTree;
copyTree.prune();
cout << "Obtaining compact representation and reconstituting tree...\n" << endl;
libzerocash::IncrementalMerkleTreeCompact compactTree = merkleTree.getCompactRepresentation();
cout << "Compact representation vector: ";
libzerocash::printVector(compactTree.getHashList());
libzerocash::IncrementalMerkleTree reconstitutedTree(compactTree);
reconstitutedTree.getRootValue(root);
cout << "New root: ";
libzerocash::printVectorAsHex(root);
cout << endl;
reconstitutedTree.insertVector(coinValues);
merkleTree.insertVector(coinValues);
reconstitutedTree.getRootValue(root);
cout << "New root (added a bunch more): ";
libzerocash::printVectorAsHex(root);
cout << endl;
merkleTree.getRootValue(root);
cout << "Old root (added a bunch more): ";
libzerocash::printVectorAsHex(root);
cout << endl;
merkle_authentication_path witness(16);
std::vector<bool> index;
libzerocash::convertIntToVector(3, index);
if (merkleTree.getWitness(index, witness) == false) {
BOOST_ERROR("Witness generation failed.");
}
cout << "Successfully created witness.\n" << endl;
cout << "Witness: " << endl;
for(size_t i = 0; i < witness.size(); i++) {
libzerocash::printVectorAsHex(witness.at(i));
}
cout << "\n" << endl;
vector<bool> wit1(SHA256_BLOCK_SIZE * 8);
vector<bool> wit2(SHA256_BLOCK_SIZE * 8);
vector<bool> wit3(SHA256_BLOCK_SIZE * 8);
vector<bool> inter_1(SHA256_BLOCK_SIZE * 8);
vector<bool> inter_2(SHA256_BLOCK_SIZE * 8);
std::vector<bool> zeros(SHA256_BLOCK_SIZE * 8, 0);
wit1 = coinValues.at(2);
libzerocash::hashVectors(coinValues.at(0), coinValues.at(1), wit2);
libzerocash::hashVectors(coinValues.at(4), zeros, inter_1);
inter_2 = zeros;
libzerocash::hashVectors(inter_1, inter_2, wit3);
BOOST_CHECK(witness.size() == 64);
for (size_t i = 0; i < 61; i++) {
BOOST_CHECK(witness.at(i) == zeros);
}
BOOST_CHECK(
(witness.at(61) == wit3) &&
(witness.at(62) == wit2) &&
(witness.at(63) == wit1)
);
}
BOOST_AUTO_TEST_CASE( SimpleTxTest ) {
cout << "\nSIMPLE TRANSACTION TEST\n" << endl;
libzerocash::timer_start("Param Generation");
auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH);
libzerocash::ZerocashParams p(
TEST_TREE_DEPTH,
&keypair
);
libzerocash::timer_stop("Param Generation");
vector<libzerocash::Coin> coins;
vector<libzerocash::Address> addrs;
cout << "Creating Addresses and Coins...\n" << endl;
for(size_t i = 0; i < 5; i++) {
addrs.push_back(libzerocash::Address::CreateNewRandomAddress());
coins.push_back(libzerocash::Coin(addrs.at(i).getPublicAddress(), i));
}
cout << "Successfully created address and coins.\n" << endl;
cout << "Creating a Mint Transaction...\n" << endl;
libzerocash::MintTransaction minttx(coins.at(0));
cout << "Successfully created a Mint Transaction.\n" << endl;
cout << "Verifying a Mint Transaction...\n" << endl;
bool minttx_res = minttx.verify();
vector<std::vector<bool>> coinValues(5);
vector<bool> temp_comVal(ZC_CM_SIZE * 8);
for(size_t i = 0; i < coinValues.size(); i++) {
libzerocash::convertBytesVectorToVector(coins.at(i).getCoinCommitment().getCommitmentValue(), temp_comVal);
coinValues.at(i) = temp_comVal;
}
cout << "Creating Merkle Tree...\n" << endl;
libzerocash::IncrementalMerkleTree merkleTree(coinValues, TEST_TREE_DEPTH);
cout << "Successfully created Merkle Tree.\n" << endl;
std::vector<bool> index;
cout << "Creating Witness 1...\n" << endl;
merkle_authentication_path witness_1(TEST_TREE_DEPTH);
libzerocash::convertIntToVector(1, index);
if (merkleTree.getWitness(index, witness_1) == false) {
BOOST_ERROR("Could not get witness");
}
cout << "Successfully created Witness 1.\n" << endl;
cout << "Creating Witness 2...\n" << endl;
merkle_authentication_path witness_2(TEST_TREE_DEPTH);
libzerocash::convertIntToVector(3, index);
if (merkleTree.getWitness(index, witness_2) == false) {
cout << "Could not get witness" << endl;
}
cout << "Successfully created Witness 2.\n" << endl;
cout << "Creating coins to spend...\n" << endl;
libzerocash::Address newAddress3 = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress3 = newAddress3.getPublicAddress();
libzerocash::Address newAddress4 = libzerocash::Address::CreateNewRandomAddress();
libzerocash::PublicAddress pubAddress4 = newAddress4.getPublicAddress();
libzerocash::Coin c_1_new(pubAddress3, 2);
libzerocash::Coin c_2_new(pubAddress4, 2);
cout << "Successfully created coins to spend.\n" << endl;
vector<bool> root_bv(ZC_ROOT_SIZE * 8);
merkleTree.getRootValue(root_bv);
vector<unsigned char> rt(ZC_ROOT_SIZE);
libzerocash::convertVectorToBytesVector(root_bv, rt);
vector<unsigned char> as(ZC_SIG_PK_SIZE, 'a');
cout << "Creating a pour transaction...\n" << endl;
libzerocash::PourTransaction pourtx(1, p,
rt,
coins.at(1), coins.at(3),
addrs.at(1), addrs.at(3),
1, 3,
witness_1, witness_2,
pubAddress3, pubAddress4,
0,
0,
as,
c_1_new, c_2_new);
cout << "Successfully created a pour transaction.\n" << endl;
std::vector<unsigned char> pubkeyHash(ZC_SIG_PK_SIZE, 'a');
cout << "Verifying a pour transaction...\n" << endl;
bool pourtx_res = pourtx.verify(p, pubkeyHash, rt);
BOOST_CHECK(minttx_res && pourtx_res);
}