From 5a2db9e2837c096092ef9c2398b81d7c80ad19d4 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Wed, 4 May 2016 18:26:16 -0600 Subject: [PATCH] libzcash: Add tests for API --- src/Makefile.gtest.include | 1 + src/gtest/test_joinsplit.cpp | 213 +++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 src/gtest/test_joinsplit.cpp diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index dd255a707..2bd780608 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -6,6 +6,7 @@ zcash_gtest_SOURCES = \ gtest/main.cpp \ gtest/test_tautology.cpp \ gtest/test_checktransaction.cpp \ + gtest/test_joinsplit.cpp \ gtest/test_noteencryption.cpp \ gtest/test_merkletree.cpp diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp new file mode 100644 index 000000000..bc41a387b --- /dev/null +++ b/src/gtest/test_joinsplit.cpp @@ -0,0 +1,213 @@ +#include + +#include "utilstrencodings.h" + +#include "zcash/prf.h" + +#include "zcash/JoinSplit.hpp" +#include "zcash/Note.hpp" +#include "zcash/NoteEncryption.hpp" +#include "zcash/IncrementalMerkleTree.hpp" + +using namespace libzcash; + +void test_full_api(ZCJoinSplit* js) +{ + // The recipient's information. + SpendingKey recipient_key = SpendingKey::random(); + PaymentAddress recipient_addr = recipient_key.address(); + + // Create the commitment tree + ZCIncrementalMerkleTree tree; + + // Set up a JoinSplit description + uint256 ephemeralKey; + uint256 randomSeed; + uint64_t vpub_old = 10; + uint64_t vpub_new = 0; + uint256 pubKeyHash = random_uint256(); + boost::array macs; + boost::array nullifiers; + boost::array commitments; + uint256 rt = tree.root(); + boost::array ciphertexts; + std::string proof; + + { + boost::array inputs = { + JSInput(), // dummy input + JSInput() // dummy input + }; + + boost::array outputs = { + JSOutput(recipient_addr, 10), + JSOutput() // dummy output + }; + + boost::array output_notes; + + // Perform the proof + proof = js->prove( + inputs, + outputs, + output_notes, + ciphertexts, + ephemeralKey, + pubKeyHash, + randomSeed, + macs, + nullifiers, + commitments, + vpub_old, + vpub_new, + rt + ); + } + + // Verify the transaction: + ASSERT_TRUE(js->verify( + proof, + pubKeyHash, + randomSeed, + macs, + nullifiers, + commitments, + vpub_old, + vpub_new, + rt + )); + + // Recipient should decrypt + // Now the recipient should spend the money again + auto h_sig = js->h_sig(randomSeed, nullifiers, pubKeyHash); + ZCNoteDecryption decryptor(recipient_key.viewing_key()); + + auto note_pt = NotePlaintext::decrypt( + decryptor, + ciphertexts[0], + ephemeralKey, + h_sig, + 0 + ); + + auto decrypted_note = note_pt.note(recipient_addr); + + ASSERT_TRUE(decrypted_note.value == 10); + + // 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(); + pubKeyHash = random_uint256(); + + { + boost::array inputs = { + JSInput(), // dummy input + JSInput(witness_recipient, decrypted_note, recipient_key) + }; + + SpendingKey second_recipient = SpendingKey::random(); + PaymentAddress second_addr = second_recipient.address(); + + boost::array outputs = { + JSOutput(second_addr, 9), + JSOutput() // dummy output + }; + + boost::array output_notes; + + // Perform the proof + proof = js->prove( + inputs, + outputs, + output_notes, + ciphertexts, + ephemeralKey, + pubKeyHash, + randomSeed, + macs, + nullifiers, + commitments, + vpub_old, + vpub_new, + rt + ); + } + + // Verify the transaction: + ASSERT_TRUE(js->verify( + proof, + pubKeyHash, + randomSeed, + macs, + nullifiers, + commitments, + vpub_old, + vpub_new, + rt + )); +} + +TEST(joinsplit, full_api_test) +{ + auto js = ZCJoinSplit::Generate(); + + test_full_api(js); + + js->saveProvingKey("./zcashTest.pk"); + js->saveVerifyingKey("./zcashTest.vk"); + + delete js; + + js = ZCJoinSplit::Unopened(); + + js->setProvingKeyPath("./zcashTest.pk"); + js->loadProvingKey(); + js->loadVerifyingKey("./zcashTest.vk"); + + test_full_api(js); + + delete js; +} + +TEST(joinsplit, note_plaintexts) +{ + uint256 a_sk = uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516847e"); + uint256 a_pk = PRF_addr_a_pk(a_sk); + uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk); + uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc); + PaymentAddress addr_pk(a_pk, pk_enc); + + uint256 h_sig; + + ZCNoteEncryption encryptor(h_sig); + uint256 epk = encryptor.get_epk(); + + Note note(a_pk, + 1945813, + random_uint256(), + random_uint256() + ); + + boost::array memo; + + NotePlaintext note_pt(note, memo); + + ZCNoteEncryption::Ciphertext ct = note_pt.encrypt(encryptor, pk_enc); + + ZCNoteDecryption decryptor(sk_enc); + + auto decrypted = NotePlaintext::decrypt(decryptor, ct, epk, h_sig, 0); + auto decrypted_note = decrypted.note(addr_pk); + + ASSERT_TRUE(decrypted_note.a_pk == note.a_pk); + ASSERT_TRUE(decrypted_note.rho == note.rho); + ASSERT_TRUE(decrypted_note.r == note.r); + ASSERT_TRUE(decrypted_note.value == note.value); + + ASSERT_TRUE(decrypted.memo == note_pt.memo); +}