Sean Bowe
8 years ago
2 changed files with 214 additions and 0 deletions
@ -0,0 +1,213 @@ |
|||
#include <gtest/gtest.h> |
|||
|
|||
#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<uint256, 2> macs; |
|||
boost::array<uint256, 2> nullifiers; |
|||
boost::array<uint256, 2> commitments; |
|||
uint256 rt = tree.root(); |
|||
boost::array<ZCNoteEncryption::Ciphertext, 2> ciphertexts; |
|||
std::string proof; |
|||
|
|||
{ |
|||
boost::array<JSInput, 2> inputs = { |
|||
JSInput(), // dummy input
|
|||
JSInput() // dummy input
|
|||
}; |
|||
|
|||
boost::array<JSOutput, 2> outputs = { |
|||
JSOutput(recipient_addr, 10), |
|||
JSOutput() // dummy output
|
|||
}; |
|||
|
|||
boost::array<Note, 2> 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<JSInput, 2> inputs = { |
|||
JSInput(), // dummy input
|
|||
JSInput(witness_recipient, decrypted_note, recipient_key) |
|||
}; |
|||
|
|||
SpendingKey second_recipient = SpendingKey::random(); |
|||
PaymentAddress second_addr = second_recipient.address(); |
|||
|
|||
boost::array<JSOutput, 2> outputs = { |
|||
JSOutput(second_addr, 9), |
|||
JSOutput() // dummy output
|
|||
}; |
|||
|
|||
boost::array<Note, 2> 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<unsigned char, ZCASH_MEMO_SIZE> 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); |
|||
} |
Loading…
Reference in new issue