From 589479fd33b8d512945ed5d485d6643c2f5b2a88 Mon Sep 17 00:00:00 2001 From: Ariel Gabizon Date: Wed, 6 Jun 2018 16:06:11 -0700 Subject: [PATCH] Extend Joinsplit tests to Groth --- src/gtest/test_joinsplit.cpp | 213 +++++++++++++++++++---------------- 1 file changed, 115 insertions(+), 98 deletions(-) diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp index 1ef62d9f5..3a8c6ad0f 100644 --- a/src/gtest/test_joinsplit.cpp +++ b/src/gtest/test_joinsplit.cpp @@ -10,7 +10,7 @@ #include "streams.h" #include "version.h" #include "serialize.h" - +#include "primitives/transaction.h" #include "zcash/JoinSplit.hpp" #include "zcash/Note.hpp" #include "zcash/NoteEncryption.hpp" @@ -22,6 +22,40 @@ using namespace libzcash; extern ZCJoinSplit* params; +typedef std::array SproutProofs; +// Make both the PHGR and Groth proof for a Sprout statement, +// and store the results in JSDescription objects. +SproutProofs makeSproutProofs( + ZCJoinSplit& js, + const std::array& inputs, + const std::array& outputs, + const uint256& joinSplitPubKey, + uint64_t vpub_old, + uint64_t vpub_new, + const uint256& rt +){ + //Making the PHGR proof + JSDescription phgr(false, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); + //Making the Groth proof + JSDescription groth(true, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); + + return {phgr, groth}; + +} + +bool verifySproutProofs( + ZCJoinSplit& js, + const SproutProofs& jsdescs, + const uint256& joinSplitPubKey +) +{ + auto verifier = libzcash::ProofVerifier::Strict(); + bool phgrPassed = jsdescs[0].Verify(js, verifier, joinSplitPubKey); + bool grothPassed = jsdescs[1].Verify(js, verifier, joinSplitPubKey); + return phgrPassed && grothPassed; +} + + void test_full_api(ZCJoinSplit* js) { // Create verification context. @@ -35,17 +69,11 @@ void test_full_api(ZCJoinSplit* js) ZCIncrementalMerkleTree tree; // Set up a JoinSplit description - uint256 ephemeralKey; - uint256 randomSeed; uint64_t vpub_old = 10; uint64_t vpub_new = 0; uint256 joinSplitPubKey = random_uint256(); - std::array macs; - std::array nullifiers; - std::array commitments; uint256 rt = tree.root(); - std::array ciphertexts; - SproutProof proof; + SproutProofs jsdescs; { std::array inputs = { @@ -60,118 +88,87 @@ void test_full_api(ZCJoinSplit* js) std::array output_notes; - // Perform the proof - proof = js->prove( - false, + // Perform the proofs + jsdescs = makeSproutProofs( + *js, inputs, outputs, - output_notes, - ciphertexts, - ephemeralKey, joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, vpub_old, vpub_new, rt ); } - auto sprout_proof = boost::get(proof); + // Verify both PHGR and Groth Proof: + ASSERT_TRUE(verifySproutProofs(*js, jsdescs, joinSplitPubKey)); - // Verify the transaction: - ASSERT_TRUE(js->verify( - sprout_proof, - verifier, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - rt - )); + // Run tests using both phgr and groth as basis for field values + for (auto jsdesc : jsdescs) + { + ZCIncrementalMerkleTree tree; + SproutProofs jsdescs2; + // Recipient should decrypt + // Now the recipient should spend the money again + auto h_sig = js->h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey); + ZCNoteDecryption decryptor(recipient_key.receiving_key()); + + auto note_pt = SproutNotePlaintext::decrypt( + decryptor, + jsdesc.ciphertexts[0], + jsdesc.ephemeralKey, + h_sig, + 0 + ); - // Recipient should decrypt - // Now the recipient should spend the money again - auto h_sig = js->h_sig(randomSeed, nullifiers, joinSplitPubKey); - ZCNoteDecryption decryptor(recipient_key.receiving_key()); + auto decrypted_note = note_pt.note(recipient_addr); - auto note_pt = SproutNotePlaintext::decrypt( - decryptor, - ciphertexts[0], - ephemeralKey, - h_sig, - 0 - ); + ASSERT_TRUE(decrypted_note.value() == 10); - auto decrypted_note = note_pt.note(recipient_addr); + // Insert the commitments from the last tx into the tree + tree.append(jsdesc.commitments[0]); + auto witness_recipient = tree.witness(); + tree.append(jsdesc.commitments[1]); + witness_recipient.append(jsdesc.commitments[1]); + vpub_old = 0; + vpub_new = 1; + rt = tree.root(); + auto joinSplitPubKey2 = random_uint256(); - ASSERT_TRUE(decrypted_note.value() == 10); + { + std::array inputs = { + JSInput(), // dummy input + JSInput(witness_recipient, decrypted_note, recipient_key) + }; - // Insert the commitments from the last tx into the tree - tree.append(commitments[0]); - auto witness_recipient = tree.witness(); - tree.append(commitments[1]); - witness_recipient.append(commitments[1]); - vpub_old = 0; - vpub_new = 1; - rt = tree.root(); - joinSplitPubKey = random_uint256(); + SproutSpendingKey second_recipient = SproutSpendingKey::random(); + SproutPaymentAddress second_addr = second_recipient.address(); - { - std::array inputs = { - JSInput(), // dummy input - JSInput(witness_recipient, decrypted_note, recipient_key) - }; + std::array outputs = { + JSOutput(second_addr, 9), + JSOutput() // dummy output + }; - SproutSpendingKey second_recipient = SproutSpendingKey::random(); - SproutPaymentAddress second_addr = second_recipient.address(); + std::array output_notes; - std::array outputs = { - JSOutput(second_addr, 9), - JSOutput() // dummy output - }; - std::array output_notes; + // Perform the proofs + jsdescs2 = makeSproutProofs( + *js, + inputs, + outputs, + joinSplitPubKey2, + vpub_old, + vpub_new, + rt + ); - // Perform the proof - proof = js->prove( - false, - inputs, - outputs, - output_notes, - ciphertexts, - ephemeralKey, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - rt - ); - } + } - sprout_proof = boost::get(proof); - // Verify the transaction: - ASSERT_TRUE(js->verify( - sprout_proof, - verifier, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - rt - )); + // Verify both PHGR and Groth Proof: + ASSERT_TRUE(verifySproutProofs(*js, jsdescs2, joinSplitPubKey2)); + } } // Invokes the API (but does not compute a proof) @@ -194,6 +191,7 @@ void invokeAPI( std::array output_notes; + // PHGR SproutProof proof = js->prove( false, inputs, @@ -211,6 +209,25 @@ void invokeAPI( rt, false ); + + // Groth + proof = js->prove( + true, + inputs, + outputs, + output_notes, + ciphertexts, + ephemeralKey, + joinSplitPubKey, + randomSeed, + macs, + nullifiers, + commitments, + vpub_old, + vpub_new, + rt, + false + ); } void invokeAPIFailure(