diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index d247e3e96..d635c5b94 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -4,6 +4,7 @@ bin_PROGRAMS += zcash-gtest # tool for generating our public parameters zcash_gtest_SOURCES = \ gtest/main.cpp \ + gtest/utils.cpp \ gtest/test_checktransaction.cpp \ gtest/json_test_vectors.cpp \ gtest/json_test_vectors.h \ @@ -19,6 +20,7 @@ zcash_gtest_SOURCES = \ gtest/test_pow.cpp \ gtest/test_random.cpp \ gtest/test_rpc.cpp \ + gtest/test_transaction.cpp \ gtest/test_circuit.cpp \ gtest/test_txid.cpp \ gtest/test_libzcash_utils.cpp \ diff --git a/src/gtest/test_random.cpp b/src/gtest/test_random.cpp index e4a2f5c41..61f81c331 100644 --- a/src/gtest/test_random.cpp +++ b/src/gtest/test_random.cpp @@ -2,15 +2,8 @@ #include "random.h" -int GenZero(int n) -{ - return 0; -} - -int GenMax(int n) -{ - return n-1; -} +extern int GenZero(int n); +extern int GenMax(int n); TEST(Random, MappedShuffle) { std::vector a {8, 4, 6, 3, 5}; diff --git a/src/gtest/test_transaction.cpp b/src/gtest/test_transaction.cpp new file mode 100644 index 000000000..a339f7652 --- /dev/null +++ b/src/gtest/test_transaction.cpp @@ -0,0 +1,85 @@ +#include + +#include "primitives/transaction.h" +#include "zcash/Note.hpp" +#include "zcash/Address.hpp" + +extern ZCJoinSplit* params; +extern int GenZero(int n); +extern int GenMax(int n); + +TEST(Transaction, JSDescriptionRandomized) { + // construct a merkle tree + ZCIncrementalMerkleTree merkleTree; + + libzcash::SpendingKey k = libzcash::SpendingKey::random(); + libzcash::PaymentAddress addr = k.address(); + + libzcash::Note note(addr.a_pk, 100, uint256(), uint256()); + + // commitment from coin + uint256 commitment = note.cm(); + + // insert commitment into the merkle tree + merkleTree.append(commitment); + + // compute the merkle root we will be working with + uint256 rt = merkleTree.root(); + + auto witness = merkleTree.witness(); + + // create JSDescription + uint256 pubKeyHash; + boost::array inputs = { + libzcash::JSInput(witness, note, k), + libzcash::JSInput() // dummy input of zero value + }; + boost::array outputs = { + libzcash::JSOutput(addr, 50), + libzcash::JSOutput(addr, 50) + }; + boost::array inputMap; + boost::array outputMap; + + { + auto jsdesc = JSDescription::Randomized( + *params, pubKeyHash, rt, + inputs, outputs, + inputMap, outputMap, + 0, 0, false); + + std::set inputSet(inputMap.begin(), inputMap.end()); + std::set expectedInputSet {0, 1}; + EXPECT_EQ(expectedInputSet, inputSet); + + std::set outputSet(outputMap.begin(), outputMap.end()); + std::set expectedOutputSet {0, 1}; + EXPECT_EQ(expectedOutputSet, outputSet); + } + + { + auto jsdesc = JSDescription::Randomized( + *params, pubKeyHash, rt, + inputs, outputs, + inputMap, outputMap, + 0, 0, false, GenZero); + + boost::array expectedInputMap {1, 0}; + boost::array expectedOutputMap {1, 0}; + EXPECT_EQ(expectedInputMap, inputMap); + EXPECT_EQ(expectedOutputMap, outputMap); + } + + { + auto jsdesc = JSDescription::Randomized( + *params, pubKeyHash, rt, + inputs, outputs, + inputMap, outputMap, + 0, 0, false, GenMax); + + boost::array expectedInputMap {0, 1}; + boost::array expectedOutputMap {0, 1}; + EXPECT_EQ(expectedInputMap, inputMap); + EXPECT_EQ(expectedOutputMap, outputMap); + } +} diff --git a/src/gtest/utils.cpp b/src/gtest/utils.cpp new file mode 100644 index 000000000..cf025162c --- /dev/null +++ b/src/gtest/utils.cpp @@ -0,0 +1,13 @@ +#include "zcash/JoinSplit.hpp" + +ZCJoinSplit* params = ZCJoinSplit::Unopened(); + +int GenZero(int n) +{ + return 0; +} + +int GenMax(int n) +{ + return n-1; +} diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 704b10a5c..5fc2a39ab 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -6,7 +6,6 @@ #include "primitives/transaction.h" #include "hash.h" -#include "random.h" #include "tinyformat.h" #include "utilstrencodings.h" @@ -52,13 +51,14 @@ JSDescription JSDescription::Randomized( boost::array& outputMap, CAmount vpub_old, CAmount vpub_new, - bool computeProof) + bool computeProof, + std::function gen) { // Randomize the order of the inputs and outputs inputMap = {0, 1}; outputMap = {0, 1}; - MappedShuffle(inputs.begin(), inputMap.begin(), ZC_NUM_JS_INPUTS, GetRandInt); - MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, GetRandInt); + MappedShuffle(inputs.begin(), inputMap.begin(), ZC_NUM_JS_INPUTS, gen); + MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen); return JSDescription( params, pubKeyHash, anchor, inputs, outputs, diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index b665033d8..9b78436c5 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -7,6 +7,7 @@ #define BITCOIN_PRIMITIVES_TRANSACTION_H #include "amount.h" +#include "random.h" #include "script/script.h" #include "serialize.h" #include "uint256.h" @@ -88,7 +89,8 @@ public: boost::array& outputMap, CAmount vpub_old, CAmount vpub_new, - bool computeProof = true // Set to false in some tests + bool computeProof = true, // Set to false in some tests + std::function gen = GetRandInt ); // Verifies that the JoinSplit proof is correct. diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index e7a932a4f..25efbd292 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -367,34 +367,6 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification) test.anchor = GetRandHash(); BOOST_CHECK(!test.Verify(*p, pubKeyHash)); } - - { - boost::array inputMap; - boost::array outputMap; - auto jsdesc = JSDescription::Randomized( - *p, pubKeyHash, rt, - inputs, outputs, - inputMap, outputMap, - 0, 0); - BOOST_CHECK(jsdesc.Verify(*p, pubKeyHash)); - - std::set inputSet; - for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) { - inputSet.insert(inputMap[i]); - } - std::set expectedInputSet {0, 1}; - BOOST_CHECK(expectedInputSet == inputSet); - - std::set outputSet; - for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - outputSet.insert(outputMap[i]); - } - std::set expectedOutputSet {0, 1}; - BOOST_CHECK(expectedOutputSet == outputSet); - } - - - delete p; } BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity) diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index c1bf5d34c..808aff6c4 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -13,7 +13,7 @@ using ::testing::Return; -ZCJoinSplit* params = ZCJoinSplit::Unopened(); +extern ZCJoinSplit* params; ACTION(ThrowLogicError) { throw std::logic_error("Boom");