Auto merge of #3206 - bitcartel:3194_polymorphic_note_class, r=str4d
Update note classes to be polymorphic Closes #3194. Lays foundation for introduction of Sapling notes through refactoring and creation of a class hierarchy for Sprout notes. This PR updates some tests, but otherwise is a no-op.
This commit is contained in:
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "zcash/prf.h"
|
#include "zcash/prf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "streams.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
#include "zcash/JoinSplit.hpp"
|
#include "zcash/JoinSplit.hpp"
|
||||||
#include "zcash/Note.hpp"
|
#include "zcash/Note.hpp"
|
||||||
@@ -52,7 +55,7 @@ void test_full_api(ZCJoinSplit* js)
|
|||||||
JSOutput() // dummy output
|
JSOutput() // dummy output
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::array<Note, 2> output_notes;
|
boost::array<SproutNote, 2> output_notes;
|
||||||
|
|
||||||
// Perform the proof
|
// Perform the proof
|
||||||
proof = js->prove(
|
proof = js->prove(
|
||||||
@@ -91,7 +94,7 @@ void test_full_api(ZCJoinSplit* js)
|
|||||||
auto h_sig = js->h_sig(randomSeed, nullifiers, pubKeyHash);
|
auto h_sig = js->h_sig(randomSeed, nullifiers, pubKeyHash);
|
||||||
ZCNoteDecryption decryptor(recipient_key.receiving_key());
|
ZCNoteDecryption decryptor(recipient_key.receiving_key());
|
||||||
|
|
||||||
auto note_pt = NotePlaintext::decrypt(
|
auto note_pt = SproutNotePlaintext::decrypt(
|
||||||
decryptor,
|
decryptor,
|
||||||
ciphertexts[0],
|
ciphertexts[0],
|
||||||
ephemeralKey,
|
ephemeralKey,
|
||||||
@@ -101,7 +104,7 @@ void test_full_api(ZCJoinSplit* js)
|
|||||||
|
|
||||||
auto decrypted_note = note_pt.note(recipient_addr);
|
auto decrypted_note = note_pt.note(recipient_addr);
|
||||||
|
|
||||||
ASSERT_TRUE(decrypted_note.value == 10);
|
ASSERT_TRUE(decrypted_note.value() == 10);
|
||||||
|
|
||||||
// Insert the commitments from the last tx into the tree
|
// Insert the commitments from the last tx into the tree
|
||||||
tree.append(commitments[0]);
|
tree.append(commitments[0]);
|
||||||
@@ -127,7 +130,7 @@ void test_full_api(ZCJoinSplit* js)
|
|||||||
JSOutput() // dummy output
|
JSOutput() // dummy output
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::array<Note, 2> output_notes;
|
boost::array<SproutNote, 2> output_notes;
|
||||||
|
|
||||||
// Perform the proof
|
// Perform the proof
|
||||||
proof = js->prove(
|
proof = js->prove(
|
||||||
@@ -180,7 +183,7 @@ void invokeAPI(
|
|||||||
boost::array<uint256, 2> commitments;
|
boost::array<uint256, 2> commitments;
|
||||||
boost::array<ZCNoteEncryption::Ciphertext, 2> ciphertexts;
|
boost::array<ZCNoteEncryption::Ciphertext, 2> ciphertexts;
|
||||||
|
|
||||||
boost::array<Note, 2> output_notes;
|
boost::array<SproutNote, 2> output_notes;
|
||||||
|
|
||||||
ZCProof proof = js->prove(
|
ZCProof proof = js->prove(
|
||||||
inputs,
|
inputs,
|
||||||
@@ -316,15 +319,15 @@ TEST(joinsplit, full_api_test)
|
|||||||
increment_note_witnesses(uint256(), witnesses, tree);
|
increment_note_witnesses(uint256(), witnesses, tree);
|
||||||
SpendingKey sk = SpendingKey::random();
|
SpendingKey sk = SpendingKey::random();
|
||||||
PaymentAddress addr = sk.address();
|
PaymentAddress addr = sk.address();
|
||||||
Note note1(addr.a_pk, 100, random_uint256(), random_uint256());
|
SproutNote note1(addr.a_pk, 100, random_uint256(), random_uint256());
|
||||||
increment_note_witnesses(note1.cm(), witnesses, tree);
|
increment_note_witnesses(note1.cm(), witnesses, tree);
|
||||||
Note note2(addr.a_pk, 100, random_uint256(), random_uint256());
|
SproutNote note2(addr.a_pk, 100, random_uint256(), random_uint256());
|
||||||
increment_note_witnesses(note2.cm(), witnesses, tree);
|
increment_note_witnesses(note2.cm(), witnesses, tree);
|
||||||
Note note3(addr.a_pk, 2100000000000001, random_uint256(), random_uint256());
|
SproutNote note3(addr.a_pk, 2100000000000001, random_uint256(), random_uint256());
|
||||||
increment_note_witnesses(note3.cm(), witnesses, tree);
|
increment_note_witnesses(note3.cm(), witnesses, tree);
|
||||||
Note note4(addr.a_pk, 1900000000000000, random_uint256(), random_uint256());
|
SproutNote note4(addr.a_pk, 1900000000000000, random_uint256(), random_uint256());
|
||||||
increment_note_witnesses(note4.cm(), witnesses, tree);
|
increment_note_witnesses(note4.cm(), witnesses, tree);
|
||||||
Note note5(addr.a_pk, 1900000000000000, random_uint256(), random_uint256());
|
SproutNote note5(addr.a_pk, 1900000000000000, random_uint256(), random_uint256());
|
||||||
increment_note_witnesses(note5.cm(), witnesses, tree);
|
increment_note_witnesses(note5.cm(), witnesses, tree);
|
||||||
|
|
||||||
// Should work
|
// Should work
|
||||||
@@ -523,7 +526,7 @@ TEST(joinsplit, note_plaintexts)
|
|||||||
ZCNoteEncryption encryptor(h_sig);
|
ZCNoteEncryption encryptor(h_sig);
|
||||||
uint256 epk = encryptor.get_epk();
|
uint256 epk = encryptor.get_epk();
|
||||||
|
|
||||||
Note note(a_pk,
|
SproutNote note(a_pk,
|
||||||
1945813,
|
1945813,
|
||||||
random_uint256(),
|
random_uint256(),
|
||||||
random_uint256()
|
random_uint256()
|
||||||
@@ -531,19 +534,52 @@ TEST(joinsplit, note_plaintexts)
|
|||||||
|
|
||||||
boost::array<unsigned char, ZC_MEMO_SIZE> memo;
|
boost::array<unsigned char, ZC_MEMO_SIZE> memo;
|
||||||
|
|
||||||
NotePlaintext note_pt(note, memo);
|
SproutNotePlaintext note_pt(note, memo);
|
||||||
|
|
||||||
ZCNoteEncryption::Ciphertext ct = note_pt.encrypt(encryptor, pk_enc);
|
ZCNoteEncryption::Ciphertext ct = note_pt.encrypt(encryptor, pk_enc);
|
||||||
|
|
||||||
ZCNoteDecryption decryptor(sk_enc);
|
ZCNoteDecryption decryptor(sk_enc);
|
||||||
|
|
||||||
auto decrypted = NotePlaintext::decrypt(decryptor, ct, epk, h_sig, 0);
|
auto decrypted = SproutNotePlaintext::decrypt(decryptor, ct, epk, h_sig, 0);
|
||||||
auto decrypted_note = decrypted.note(addr_pk);
|
auto decrypted_note = decrypted.note(addr_pk);
|
||||||
|
|
||||||
ASSERT_TRUE(decrypted_note.a_pk == note.a_pk);
|
ASSERT_TRUE(decrypted_note.a_pk == note.a_pk);
|
||||||
ASSERT_TRUE(decrypted_note.rho == note.rho);
|
ASSERT_TRUE(decrypted_note.rho == note.rho);
|
||||||
ASSERT_TRUE(decrypted_note.r == note.r);
|
ASSERT_TRUE(decrypted_note.r == note.r);
|
||||||
ASSERT_TRUE(decrypted_note.value == note.value);
|
ASSERT_TRUE(decrypted_note.value() == note.value());
|
||||||
|
|
||||||
ASSERT_TRUE(decrypted.memo == note_pt.memo);
|
ASSERT_TRUE(decrypted.memo() == note_pt.memo());
|
||||||
|
|
||||||
|
// Check serialization of note plaintext
|
||||||
|
CDataStream ss(SER_DISK, PROTOCOL_VERSION);
|
||||||
|
ss << note_pt;
|
||||||
|
SproutNotePlaintext note_pt2;
|
||||||
|
ss >> note_pt2;
|
||||||
|
ASSERT_EQ(note_pt.value(), note.value());
|
||||||
|
ASSERT_EQ(note_pt.value(), note_pt2.value());
|
||||||
|
ASSERT_EQ(note_pt.memo(), note_pt2.memo());
|
||||||
|
ASSERT_EQ(note_pt.rho, note_pt2.rho);
|
||||||
|
ASSERT_EQ(note_pt.r, note_pt2.r);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(joinsplit, note_class)
|
||||||
|
{
|
||||||
|
uint252 a_sk = uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516840e"));
|
||||||
|
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);
|
||||||
|
|
||||||
|
SproutNote note(a_pk,
|
||||||
|
1945813,
|
||||||
|
random_uint256(),
|
||||||
|
random_uint256());
|
||||||
|
|
||||||
|
SproutNote clone = note;
|
||||||
|
ASSERT_NE(¬e, &clone);
|
||||||
|
ASSERT_EQ(note.value(), clone.value());
|
||||||
|
ASSERT_EQ(note.cm(), clone.cm());
|
||||||
|
ASSERT_EQ(note.rho, clone.rho);
|
||||||
|
ASSERT_EQ(note.r, clone.r);
|
||||||
|
ASSERT_EQ(note.a_pk, clone.a_pk);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ TEST(Transaction, JSDescriptionRandomized) {
|
|||||||
libzcash::SpendingKey k = libzcash::SpendingKey::random();
|
libzcash::SpendingKey k = libzcash::SpendingKey::random();
|
||||||
libzcash::PaymentAddress addr = k.address();
|
libzcash::PaymentAddress addr = k.address();
|
||||||
|
|
||||||
libzcash::Note note(addr.a_pk, 100, uint256(), uint256());
|
libzcash::SproutNote note(addr.a_pk, 100, uint256(), uint256());
|
||||||
|
|
||||||
// commitment from coin
|
// commitment from coin
|
||||||
uint256 commitment = note.cm();
|
uint256 commitment = note.cm();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ JSDescription::JSDescription(ZCJoinSplit& params,
|
|||||||
uint256 *esk // payment disclosure
|
uint256 *esk // payment disclosure
|
||||||
) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor)
|
) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor)
|
||||||
{
|
{
|
||||||
boost::array<libzcash::Note, ZC_NUM_JS_OUTPUTS> notes;
|
boost::array<libzcash::SproutNote, ZC_NUM_JS_OUTPUTS> notes;
|
||||||
|
|
||||||
proof = params.prove(
|
proof = params.prove(
|
||||||
inputs,
|
inputs,
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ uint256 appendRandomCommitment(ZCIncrementalMerkleTree &tree)
|
|||||||
libzcash::SpendingKey k = libzcash::SpendingKey::random();
|
libzcash::SpendingKey k = libzcash::SpendingKey::random();
|
||||||
libzcash::PaymentAddress addr = k.address();
|
libzcash::PaymentAddress addr = k.address();
|
||||||
|
|
||||||
libzcash::Note note(addr.a_pk, 0, uint256(), uint256());
|
libzcash::SproutNote note(addr.a_pk, 0, uint256(), uint256());
|
||||||
|
|
||||||
auto cm = note.cm();
|
auto cm = note.cm();
|
||||||
tree.append(cm);
|
tree.append(cm);
|
||||||
|
|||||||
@@ -1183,7 +1183,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
|
|||||||
BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
|
BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
info.notes.push_back(Note());
|
info.notes.push_back(SproutNote());
|
||||||
try {
|
try {
|
||||||
proxy.perform_joinsplit(info);
|
proxy.perform_joinsplit(info);
|
||||||
} catch (const std::runtime_error & e) {
|
} catch (const std::runtime_error & e) {
|
||||||
@@ -1721,7 +1721,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals)
|
|||||||
BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
|
BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
info.notes.push_back(Note());
|
info.notes.push_back(SproutNote());
|
||||||
try {
|
try {
|
||||||
proxy.perform_joinsplit(info);
|
proxy.perform_joinsplit(info);
|
||||||
BOOST_FAIL("Should have caused an error");
|
BOOST_FAIL("Should have caused an error");
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
|
|||||||
libzcash::SpendingKey k = libzcash::SpendingKey::random();
|
libzcash::SpendingKey k = libzcash::SpendingKey::random();
|
||||||
libzcash::PaymentAddress addr = k.address();
|
libzcash::PaymentAddress addr = k.address();
|
||||||
|
|
||||||
libzcash::Note note(addr.a_pk, 100, uint256(), uint256());
|
libzcash::SproutNote note(addr.a_pk, 100, uint256(), uint256());
|
||||||
|
|
||||||
// commitment from coin
|
// commitment from coin
|
||||||
uint256 commitment = note.cm();
|
uint256 commitment = note.cm();
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ CWalletTx GetValidReceive(ZCJoinSplit& params,
|
|||||||
libzcash::JSOutput(sk.address(), value)
|
libzcash::JSOutput(sk.address(), value)
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::array<libzcash::Note, 2> output_notes;
|
|
||||||
|
|
||||||
// Prepare JoinSplits
|
// Prepare JoinSplits
|
||||||
uint256 rt;
|
uint256 rt;
|
||||||
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
|
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
|
||||||
@@ -63,12 +61,12 @@ CWalletTx GetValidReceive(ZCJoinSplit& params,
|
|||||||
return wtx;
|
return wtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
libzcash::Note GetNote(ZCJoinSplit& params,
|
libzcash::SproutNote GetNote(ZCJoinSplit& params,
|
||||||
const libzcash::SpendingKey& sk,
|
const libzcash::SpendingKey& sk,
|
||||||
const CTransaction& tx, size_t js, size_t n) {
|
const CTransaction& tx, size_t js, size_t n) {
|
||||||
ZCNoteDecryption decryptor {sk.receiving_key()};
|
ZCNoteDecryption decryptor {sk.receiving_key()};
|
||||||
auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey);
|
auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey);
|
||||||
auto note_pt = libzcash::NotePlaintext::decrypt(
|
auto note_pt = libzcash::SproutNotePlaintext::decrypt(
|
||||||
decryptor,
|
decryptor,
|
||||||
tx.vjoinsplit[js].ciphertexts[n],
|
tx.vjoinsplit[js].ciphertexts[n],
|
||||||
tx.vjoinsplit[js].ephemeralKey,
|
tx.vjoinsplit[js].ephemeralKey,
|
||||||
@@ -79,7 +77,7 @@ libzcash::Note GetNote(ZCJoinSplit& params,
|
|||||||
|
|
||||||
CWalletTx GetValidSpend(ZCJoinSplit& params,
|
CWalletTx GetValidSpend(ZCJoinSplit& params,
|
||||||
const libzcash::SpendingKey& sk,
|
const libzcash::SpendingKey& sk,
|
||||||
const libzcash::Note& note, CAmount value) {
|
const libzcash::SproutNote& note, CAmount value) {
|
||||||
CMutableTransaction mtx;
|
CMutableTransaction mtx;
|
||||||
mtx.vout.resize(2);
|
mtx.vout.resize(2);
|
||||||
mtx.vout[0].nValue = value;
|
mtx.vout[0].nValue = value;
|
||||||
@@ -98,14 +96,14 @@ CWalletTx GetValidSpend(ZCJoinSplit& params,
|
|||||||
libzcash::JSInput dummyin;
|
libzcash::JSInput dummyin;
|
||||||
|
|
||||||
{
|
{
|
||||||
if (note.value > value) {
|
if (note.value() > value) {
|
||||||
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
|
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
|
||||||
libzcash::PaymentAddress dummyaddr = dummykey.address();
|
libzcash::PaymentAddress dummyaddr = dummykey.address();
|
||||||
dummyout = libzcash::JSOutput(dummyaddr, note.value - value);
|
dummyout = libzcash::JSOutput(dummyaddr, note.value() - value);
|
||||||
} else if (note.value < value) {
|
} else if (note.value() < value) {
|
||||||
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
|
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
|
||||||
libzcash::PaymentAddress dummyaddr = dummykey.address();
|
libzcash::PaymentAddress dummyaddr = dummykey.address();
|
||||||
libzcash::Note dummynote(dummyaddr.a_pk, (value - note.value), uint256(), uint256());
|
libzcash::SproutNote dummynote(dummyaddr.a_pk, (value - note.value()), uint256(), uint256());
|
||||||
tree.append(dummynote.cm());
|
tree.append(dummynote.cm());
|
||||||
dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey);
|
dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey);
|
||||||
}
|
}
|
||||||
@@ -123,8 +121,6 @@ CWalletTx GetValidSpend(ZCJoinSplit& params,
|
|||||||
libzcash::JSOutput() // dummy output
|
libzcash::JSOutput() // dummy output
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::array<libzcash::Note, 2> output_notes;
|
|
||||||
|
|
||||||
// Prepare JoinSplits
|
// Prepare JoinSplits
|
||||||
uint256 rt = tree.root();
|
uint256 rt = tree.root();
|
||||||
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
|
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
CWalletTx GetValidReceive(ZCJoinSplit& params,
|
CWalletTx GetValidReceive(ZCJoinSplit& params,
|
||||||
const libzcash::SpendingKey& sk, CAmount value,
|
const libzcash::SpendingKey& sk, CAmount value,
|
||||||
bool randomInputs);
|
bool randomInputs);
|
||||||
libzcash::Note GetNote(ZCJoinSplit& params,
|
libzcash::SproutNote GetNote(ZCJoinSplit& params,
|
||||||
const libzcash::SpendingKey& sk,
|
const libzcash::SpendingKey& sk,
|
||||||
const CTransaction& tx, size_t js, size_t n);
|
const CTransaction& tx, size_t js, size_t n);
|
||||||
CWalletTx GetValidSpend(ZCJoinSplit& params,
|
CWalletTx GetValidSpend(ZCJoinSplit& params,
|
||||||
const libzcash::SpendingKey& sk,
|
const libzcash::SpendingKey& sk,
|
||||||
const libzcash::Note& note, CAmount value);
|
const libzcash::SproutNote& note, CAmount value);
|
||||||
|
|||||||
@@ -455,22 +455,22 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||||||
ZCNoteDecryption decryptor(changeKey.receiving_key());
|
ZCNoteDecryption decryptor(changeKey.receiving_key());
|
||||||
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
|
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
|
||||||
try {
|
try {
|
||||||
NotePlaintext plaintext = NotePlaintext::decrypt(
|
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
|
||||||
decryptor,
|
decryptor,
|
||||||
prevJoinSplit.ciphertexts[changeOutputIndex],
|
prevJoinSplit.ciphertexts[changeOutputIndex],
|
||||||
prevJoinSplit.ephemeralKey,
|
prevJoinSplit.ephemeralKey,
|
||||||
hSig,
|
hSig,
|
||||||
(unsigned char)changeOutputIndex);
|
(unsigned char)changeOutputIndex);
|
||||||
|
|
||||||
Note note = plaintext.note(changeAddress);
|
SproutNote note = plaintext.note(changeAddress);
|
||||||
info.notes.push_back(note);
|
info.notes.push_back(note);
|
||||||
info.zkeys.push_back(changeKey);
|
info.zkeys.push_back(changeKey);
|
||||||
|
|
||||||
jsInputValue += plaintext.value;
|
jsInputValue += plaintext.value();
|
||||||
|
|
||||||
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
|
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
|
||||||
getId(),
|
getId(),
|
||||||
FormatMoney(plaintext.value));
|
FormatMoney(plaintext.value()));
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error decrypting output note of previous JoinSplit: %s", e.what()));
|
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error decrypting output note of previous JoinSplit: %s", e.what()));
|
||||||
@@ -481,7 +481,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||||||
//
|
//
|
||||||
// Consume spendable non-change notes
|
// Consume spendable non-change notes
|
||||||
//
|
//
|
||||||
std::vector<Note> vInputNotes;
|
std::vector<SproutNote> vInputNotes;
|
||||||
std::vector<SpendingKey> vInputZKeys;
|
std::vector<SpendingKey> vInputZKeys;
|
||||||
std::vector<JSOutPoint> vOutPoints;
|
std::vector<JSOutPoint> vOutPoints;
|
||||||
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
||||||
@@ -490,7 +490,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||||||
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
|
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
|
||||||
MergeToAddressInputNote t = zInputsDeque.front();
|
MergeToAddressInputNote t = zInputsDeque.front();
|
||||||
JSOutPoint jso = std::get<0>(t);
|
JSOutPoint jso = std::get<0>(t);
|
||||||
Note note = std::get<1>(t);
|
SproutNote note = std::get<1>(t);
|
||||||
CAmount noteFunds = std::get<2>(t);
|
CAmount noteFunds = std::get<2>(t);
|
||||||
SpendingKey zkey = std::get<3>(t);
|
SpendingKey zkey = std::get<3>(t);
|
||||||
zInputsDeque.pop_front();
|
zInputsDeque.pop_front();
|
||||||
@@ -753,7 +753,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
|||||||
getId(),
|
getId(),
|
||||||
tx_.vjoinsplit.size(),
|
tx_.vjoinsplit.size(),
|
||||||
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
||||||
FormatMoney(info.vjsin[0].note.value), FormatMoney(info.vjsin[1].note.value),
|
FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()),
|
||||||
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value));
|
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value));
|
||||||
|
|
||||||
// Generate the proof, this can take over a minute.
|
// Generate the proof, this can take over a minute.
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ using namespace libzcash;
|
|||||||
typedef std::tuple<COutPoint, CAmount> MergeToAddressInputUTXO;
|
typedef std::tuple<COutPoint, CAmount> MergeToAddressInputUTXO;
|
||||||
|
|
||||||
// Input JSOP is a tuple of JSOutpoint, note, amount, spending key
|
// Input JSOP is a tuple of JSOutpoint, note, amount, spending key
|
||||||
typedef std::tuple<JSOutPoint, Note, CAmount, SpendingKey> MergeToAddressInputNote;
|
typedef std::tuple<JSOutPoint, SproutNote, CAmount, SpendingKey> MergeToAddressInputNote;
|
||||||
|
|
||||||
// A recipient is a tuple of address, memo (optional if zaddr)
|
// A recipient is a tuple of address, memo (optional if zaddr)
|
||||||
typedef std::tuple<std::string, std::string> MergeToAddressRecipient;
|
typedef std::tuple<std::string, std::string> MergeToAddressRecipient;
|
||||||
@@ -37,7 +37,7 @@ typedef std::tuple<std::string, std::string> MergeToAddressRecipient;
|
|||||||
struct MergeToAddressJSInfo {
|
struct MergeToAddressJSInfo {
|
||||||
std::vector<JSInput> vjsin;
|
std::vector<JSInput> vjsin;
|
||||||
std::vector<JSOutput> vjsout;
|
std::vector<JSOutput> vjsout;
|
||||||
std::vector<Note> notes;
|
std::vector<SproutNote> notes;
|
||||||
std::vector<SpendingKey> zkeys;
|
std::vector<SpendingKey> zkeys;
|
||||||
CAmount vpub_old = 0;
|
CAmount vpub_old = 0;
|
||||||
CAmount vpub_new = 0;
|
CAmount vpub_new = 0;
|
||||||
|
|||||||
@@ -571,21 +571,21 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
ZCNoteDecryption decryptor(spendingkey_.receiving_key());
|
ZCNoteDecryption decryptor(spendingkey_.receiving_key());
|
||||||
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
|
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
|
||||||
try {
|
try {
|
||||||
NotePlaintext plaintext = NotePlaintext::decrypt(
|
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
|
||||||
decryptor,
|
decryptor,
|
||||||
prevJoinSplit.ciphertexts[changeOutputIndex],
|
prevJoinSplit.ciphertexts[changeOutputIndex],
|
||||||
prevJoinSplit.ephemeralKey,
|
prevJoinSplit.ephemeralKey,
|
||||||
hSig,
|
hSig,
|
||||||
(unsigned char) changeOutputIndex);
|
(unsigned char) changeOutputIndex);
|
||||||
|
|
||||||
Note note = plaintext.note(frompaymentaddress_);
|
SproutNote note = plaintext.note(frompaymentaddress_);
|
||||||
info.notes.push_back(note);
|
info.notes.push_back(note);
|
||||||
|
|
||||||
jsInputValue += plaintext.value;
|
jsInputValue += plaintext.value();
|
||||||
|
|
||||||
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
|
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
|
||||||
getId(),
|
getId(),
|
||||||
FormatMoney(plaintext.value)
|
FormatMoney(plaintext.value())
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
@@ -597,7 +597,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
//
|
//
|
||||||
// Consume spendable non-change notes
|
// Consume spendable non-change notes
|
||||||
//
|
//
|
||||||
std::vector<Note> vInputNotes;
|
std::vector<SproutNote> vInputNotes;
|
||||||
std::vector<JSOutPoint> vOutPoints;
|
std::vector<JSOutPoint> vOutPoints;
|
||||||
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
||||||
uint256 inputAnchor;
|
uint256 inputAnchor;
|
||||||
@@ -605,7 +605,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
|
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
|
||||||
SendManyInputJSOP t = zInputsDeque.front();
|
SendManyInputJSOP t = zInputsDeque.front();
|
||||||
JSOutPoint jso = std::get<0>(t);
|
JSOutPoint jso = std::get<0>(t);
|
||||||
Note note = std::get<1>(t);
|
SproutNote note = std::get<1>(t);
|
||||||
CAmount noteFunds = std::get<2>(t);
|
CAmount noteFunds = std::get<2>(t);
|
||||||
zInputsDeque.pop_front();
|
zInputsDeque.pop_front();
|
||||||
|
|
||||||
@@ -877,21 +877,21 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
|
|||||||
|
|
||||||
|
|
||||||
bool AsyncRPCOperation_sendmany::find_unspent_notes() {
|
bool AsyncRPCOperation_sendmany::find_unspent_notes() {
|
||||||
std::vector<CNotePlaintextEntry> entries;
|
std::vector<CSproutNotePlaintextEntry> entries;
|
||||||
{
|
{
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
pwalletMain->GetFilteredNotes(entries, fromaddress_, mindepth_);
|
pwalletMain->GetFilteredNotes(entries, fromaddress_, mindepth_);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CNotePlaintextEntry & entry : entries) {
|
for (CSproutNotePlaintextEntry & entry : entries) {
|
||||||
z_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(frompaymentaddress_), CAmount(entry.plaintext.value)));
|
z_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(frompaymentaddress_), CAmount(entry.plaintext.value())));
|
||||||
std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end());
|
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
|
||||||
LogPrint("zrpcunsafe", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n",
|
LogPrint("zrpcunsafe", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n",
|
||||||
getId(),
|
getId(),
|
||||||
entry.jsop.hash.ToString().substr(0, 10),
|
entry.jsop.hash.ToString().substr(0, 10),
|
||||||
entry.jsop.js,
|
entry.jsop.js,
|
||||||
int(entry.jsop.n), // uint8_t
|
int(entry.jsop.n), // uint8_t
|
||||||
FormatMoney(entry.plaintext.value),
|
FormatMoney(entry.plaintext.value()),
|
||||||
HexStr(data).substr(0, 10)
|
HexStr(data).substr(0, 10)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -968,7 +968,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
|
|||||||
getId(),
|
getId(),
|
||||||
tx_.vjoinsplit.size(),
|
tx_.vjoinsplit.size(),
|
||||||
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
||||||
FormatMoney(info.vjsin[0].note.value), FormatMoney(info.vjsin[1].note.value),
|
FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()),
|
||||||
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)
|
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
|
|||||||
typedef std::tuple<uint256, int, CAmount, bool> SendManyInputUTXO;
|
typedef std::tuple<uint256, int, CAmount, bool> SendManyInputUTXO;
|
||||||
|
|
||||||
// Input JSOP is a tuple of JSOutpoint, note and amount
|
// Input JSOP is a tuple of JSOutpoint, note and amount
|
||||||
typedef std::tuple<JSOutPoint, Note, CAmount> SendManyInputJSOP;
|
typedef std::tuple<JSOutPoint, SproutNote, CAmount> SendManyInputJSOP;
|
||||||
|
|
||||||
// Package of info which is passed to perform_joinsplit methods.
|
// Package of info which is passed to perform_joinsplit methods.
|
||||||
struct AsyncJoinSplitInfo
|
struct AsyncJoinSplitInfo
|
||||||
{
|
{
|
||||||
std::vector<JSInput> vjsin;
|
std::vector<JSInput> vjsin;
|
||||||
std::vector<JSOutput> vjsout;
|
std::vector<JSOutput> vjsout;
|
||||||
std::vector<Note> notes;
|
std::vector<SproutNote> notes;
|
||||||
CAmount vpub_old = 0;
|
CAmount vpub_old = 0;
|
||||||
CAmount vpub_new = 0;
|
CAmount vpub_new = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
|
|||||||
getId(),
|
getId(),
|
||||||
tx_.vjoinsplit.size(),
|
tx_.vjoinsplit.size(),
|
||||||
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
||||||
FormatMoney(info.vjsin[0].note.value), FormatMoney(info.vjsin[1].note.value),
|
FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()),
|
||||||
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)
|
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -72,13 +72,13 @@ CWalletTx GetValidReceive(const libzcash::SpendingKey& sk, CAmount value, bool r
|
|||||||
return GetValidReceive(*params, sk, value, randomInputs);
|
return GetValidReceive(*params, sk, value, randomInputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
libzcash::Note GetNote(const libzcash::SpendingKey& sk,
|
libzcash::SproutNote GetNote(const libzcash::SpendingKey& sk,
|
||||||
const CTransaction& tx, size_t js, size_t n) {
|
const CTransaction& tx, size_t js, size_t n) {
|
||||||
return GetNote(*params, sk, tx, js, n);
|
return GetNote(*params, sk, tx, js, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
CWalletTx GetValidSpend(const libzcash::SpendingKey& sk,
|
CWalletTx GetValidSpend(const libzcash::SpendingKey& sk,
|
||||||
const libzcash::Note& note, CAmount value) {
|
const libzcash::SproutNote& note, CAmount value) {
|
||||||
return GetValidSpend(*params, sk, note, value);
|
return GetValidSpend(*params, sk, note, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ TEST(wallet_tests, find_unspent_notes) {
|
|||||||
EXPECT_FALSE(wallet.IsSpent(nullifier));
|
EXPECT_FALSE(wallet.IsSpent(nullifier));
|
||||||
|
|
||||||
// We currently have an unspent and unconfirmed note in the wallet (depth of -1)
|
// We currently have an unspent and unconfirmed note in the wallet (depth of -1)
|
||||||
std::vector<CNotePlaintextEntry> entries;
|
std::vector<CSproutNotePlaintextEntry> entries;
|
||||||
wallet.GetFilteredNotes(entries, "", 0);
|
wallet.GetFilteredNotes(entries, "", 0);
|
||||||
EXPECT_EQ(0, entries.size());
|
EXPECT_EQ(0, entries.size());
|
||||||
entries.clear();
|
entries.clear();
|
||||||
|
|||||||
@@ -274,16 +274,16 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
CDataStream ssPlain(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssPlain(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ssPlain << plaintext;
|
ssPlain << plaintext;
|
||||||
NotePlaintext npt;
|
SproutNotePlaintext npt;
|
||||||
ssPlain >> npt;
|
ssPlain >> npt;
|
||||||
|
|
||||||
string memoHexString = HexStr(npt.memo.data(), npt.memo.data() + npt.memo.size());
|
string memoHexString = HexStr(npt.memo().data(), npt.memo().data() + npt.memo().size());
|
||||||
o.push_back(Pair("memo", memoHexString));
|
o.push_back(Pair("memo", memoHexString));
|
||||||
o.push_back(Pair("value", ValueFromAmount(npt.value)));
|
o.push_back(Pair("value", ValueFromAmount(npt.value())));
|
||||||
|
|
||||||
// Check the blockchain commitment matches decrypted note commitment
|
// Check the blockchain commitment matches decrypted note commitment
|
||||||
uint256 cm_blockchain = jsdesc.commitments[pd.payload.n];
|
uint256 cm_blockchain = jsdesc.commitments[pd.payload.n];
|
||||||
Note note = npt.note(zaddr);
|
SproutNote note = npt.note(zaddr);
|
||||||
uint256 cm_decrypted = note.cm();
|
uint256 cm_decrypted = note.cm();
|
||||||
bool cm_match = (cm_decrypted == cm_blockchain);
|
bool cm_match = (cm_decrypted == cm_blockchain);
|
||||||
o.push_back(Pair("commitmentMatch", cm_match));
|
o.push_back(Pair("commitmentMatch", cm_match));
|
||||||
|
|||||||
@@ -2537,9 +2537,9 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||||||
UniValue results(UniValue::VARR);
|
UniValue results(UniValue::VARR);
|
||||||
|
|
||||||
if (zaddrs.size() > 0) {
|
if (zaddrs.size() > 0) {
|
||||||
std::vector<CUnspentNotePlaintextEntry> entries;
|
std::vector<CUnspentSproutNotePlaintextEntry> entries;
|
||||||
pwalletMain->GetUnspentFilteredNotes(entries, zaddrs, nMinDepth, nMaxDepth, !fIncludeWatchonly);
|
pwalletMain->GetUnspentFilteredNotes(entries, zaddrs, nMinDepth, nMaxDepth, !fIncludeWatchonly);
|
||||||
for (CUnspentNotePlaintextEntry & entry : entries) {
|
for (CUnspentSproutNotePlaintextEntry & entry : entries) {
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
|
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
|
||||||
obj.push_back(Pair("jsindex", (int)entry.jsop.js ));
|
obj.push_back(Pair("jsindex", (int)entry.jsop.js ));
|
||||||
@@ -2547,8 +2547,8 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||||||
obj.push_back(Pair("confirmations", entry.nHeight));
|
obj.push_back(Pair("confirmations", entry.nHeight));
|
||||||
obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(entry.address)));
|
obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(entry.address)));
|
||||||
obj.push_back(Pair("address", CZCPaymentAddress(entry.address).ToString()));
|
obj.push_back(Pair("address", CZCPaymentAddress(entry.address).ToString()));
|
||||||
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value))));
|
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
|
||||||
std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end());
|
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
|
||||||
obj.push_back(Pair("memo", HexStr(data)));
|
obj.push_back(Pair("memo", HexStr(data)));
|
||||||
results.push_back(obj);
|
results.push_back(obj);
|
||||||
}
|
}
|
||||||
@@ -2807,7 +2807,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
ZCNoteDecryption decryptor(k.receiving_key());
|
ZCNoteDecryption decryptor(k.receiving_key());
|
||||||
|
|
||||||
NotePlaintext npt = NotePlaintext::decrypt(
|
SproutNotePlaintext npt = SproutNotePlaintext::decrypt(
|
||||||
decryptor,
|
decryptor,
|
||||||
ct,
|
ct,
|
||||||
epk,
|
epk,
|
||||||
@@ -2815,7 +2815,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
|
|||||||
nonce
|
nonce
|
||||||
);
|
);
|
||||||
PaymentAddress payment_addr = k.address();
|
PaymentAddress payment_addr = k.address();
|
||||||
Note decrypted_note = npt.note(payment_addr);
|
SproutNote decrypted_note = npt.note(payment_addr);
|
||||||
|
|
||||||
assert(pwalletMain != NULL);
|
assert(pwalletMain != NULL);
|
||||||
std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
|
std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
|
||||||
@@ -2831,7 +2831,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
|
|||||||
ss << npt;
|
ss << npt;
|
||||||
|
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value)));
|
result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value())));
|
||||||
result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
|
result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
|
||||||
result.push_back(Pair("exists", (bool) witnesses[0]));
|
result.push_back(Pair("exists", (bool) witnesses[0]));
|
||||||
return result;
|
return result;
|
||||||
@@ -2889,7 +2889,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
std::vector<JSInput> vjsin;
|
std::vector<JSInput> vjsin;
|
||||||
std::vector<JSOutput> vjsout;
|
std::vector<JSOutput> vjsout;
|
||||||
std::vector<Note> notes;
|
std::vector<SproutNote> notes;
|
||||||
std::vector<SpendingKey> keys;
|
std::vector<SpendingKey> keys;
|
||||||
std::vector<uint256> commitments;
|
std::vector<uint256> commitments;
|
||||||
|
|
||||||
@@ -2899,7 +2899,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
keys.push_back(k);
|
keys.push_back(k);
|
||||||
|
|
||||||
NotePlaintext npt;
|
SproutNotePlaintext npt;
|
||||||
|
|
||||||
{
|
{
|
||||||
CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
|
||||||
@@ -2907,7 +2907,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PaymentAddress addr = k.address();
|
PaymentAddress addr = k.address();
|
||||||
Note note = npt.note(addr);
|
SproutNote note = npt.note(addr);
|
||||||
notes.push_back(note);
|
notes.push_back(note);
|
||||||
commitments.push_back(note.cm());
|
commitments.push_back(note.cm());
|
||||||
}
|
}
|
||||||
@@ -3173,11 +3173,11 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign
|
|||||||
|
|
||||||
CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
|
CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
|
||||||
CAmount balance = 0;
|
CAmount balance = 0;
|
||||||
std::vector<CNotePlaintextEntry> entries;
|
std::vector<CSproutNotePlaintextEntry> entries;
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
pwalletMain->GetFilteredNotes(entries, address, minDepth, true, ignoreUnspendable);
|
pwalletMain->GetFilteredNotes(entries, address, minDepth, true, ignoreUnspendable);
|
||||||
for (auto & entry : entries) {
|
for (auto & entry : entries) {
|
||||||
balance += CAmount(entry.plaintext.value);
|
balance += CAmount(entry.plaintext.value());
|
||||||
}
|
}
|
||||||
return balance;
|
return balance;
|
||||||
}
|
}
|
||||||
@@ -3233,13 +3233,13 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
|
|
||||||
UniValue result(UniValue::VARR);
|
UniValue result(UniValue::VARR);
|
||||||
std::vector<CNotePlaintextEntry> entries;
|
std::vector<CSproutNotePlaintextEntry> entries;
|
||||||
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
|
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
|
||||||
for (CNotePlaintextEntry & entry : entries) {
|
for (CSproutNotePlaintextEntry & entry : entries) {
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
|
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
|
||||||
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value))));
|
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
|
||||||
std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end());
|
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
|
||||||
obj.push_back(Pair("memo", HexStr(data)));
|
obj.push_back(Pair("memo", HexStr(data)));
|
||||||
// (txid, jsindex, jsoutindex) is needed to globally identify a note
|
// (txid, jsindex, jsoutindex) is needed to globally identify a note
|
||||||
obj.push_back(Pair("jsindex", entry.jsop.js));
|
obj.push_back(Pair("jsindex", entry.jsop.js));
|
||||||
@@ -4138,13 +4138,13 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
if (useAny || useAnyNote || zaddrs.size() > 0) {
|
if (useAny || useAnyNote || zaddrs.size() > 0) {
|
||||||
// Get available notes
|
// Get available notes
|
||||||
std::vector<CNotePlaintextEntry> entries;
|
std::vector<CSproutNotePlaintextEntry> entries;
|
||||||
pwalletMain->GetFilteredNotes(entries, zaddrs);
|
pwalletMain->GetFilteredNotes(entries, zaddrs);
|
||||||
|
|
||||||
// Find unspent notes and update estimated size
|
// Find unspent notes and update estimated size
|
||||||
for (CNotePlaintextEntry& entry : entries) {
|
for (CSproutNotePlaintextEntry& entry : entries) {
|
||||||
noteCounter++;
|
noteCounter++;
|
||||||
CAmount nValue = entry.plaintext.value;
|
CAmount nValue = entry.plaintext.value();
|
||||||
|
|
||||||
if (!maxedOutNotesFlag) {
|
if (!maxedOutNotesFlag) {
|
||||||
// If we haven't added any notes yet and the merge is to a
|
// If we haven't added any notes yet and the merge is to a
|
||||||
|
|||||||
@@ -1264,7 +1264,7 @@ boost::optional<uint256> CWallet::GetNoteNullifier(const JSDescription& jsdesc,
|
|||||||
uint8_t n) const
|
uint8_t n) const
|
||||||
{
|
{
|
||||||
boost::optional<uint256> ret;
|
boost::optional<uint256> ret;
|
||||||
auto note_pt = libzcash::NotePlaintext::decrypt(
|
auto note_pt = libzcash::SproutNotePlaintext::decrypt(
|
||||||
dec,
|
dec,
|
||||||
jsdesc.ciphertexts[n],
|
jsdesc.ciphertexts[n],
|
||||||
jsdesc.ephemeralKey,
|
jsdesc.ephemeralKey,
|
||||||
@@ -3712,7 +3712,7 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
|
|||||||
* Find notes in the wallet filtered by payment address, min depth and ability to spend.
|
* Find notes in the wallet filtered by payment address, min depth and ability to spend.
|
||||||
* These notes are decrypted and added to the output parameter vector, outEntries.
|
* These notes are decrypted and added to the output parameter vector, outEntries.
|
||||||
*/
|
*/
|
||||||
void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent, bool ignoreUnspendable)
|
void CWallet::GetFilteredNotes(std::vector<CSproutNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent, bool ignoreUnspendable)
|
||||||
{
|
{
|
||||||
std::set<PaymentAddress> filterAddresses;
|
std::set<PaymentAddress> filterAddresses;
|
||||||
|
|
||||||
@@ -3728,7 +3728,7 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
|
|||||||
* These notes are decrypted and added to the output parameter vector, outEntries.
|
* These notes are decrypted and added to the output parameter vector, outEntries.
|
||||||
*/
|
*/
|
||||||
void CWallet::GetFilteredNotes(
|
void CWallet::GetFilteredNotes(
|
||||||
std::vector<CNotePlaintextEntry>& outEntries,
|
std::vector<CSproutNotePlaintextEntry>& outEntries,
|
||||||
std::set<PaymentAddress>& filterAddresses,
|
std::set<PaymentAddress>& filterAddresses,
|
||||||
int minDepth,
|
int minDepth,
|
||||||
bool ignoreSpent,
|
bool ignoreSpent,
|
||||||
@@ -3786,14 +3786,14 @@ void CWallet::GetFilteredNotes(
|
|||||||
// determine amount of funds in the note
|
// determine amount of funds in the note
|
||||||
auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
|
auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
|
||||||
try {
|
try {
|
||||||
NotePlaintext plaintext = NotePlaintext::decrypt(
|
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
|
||||||
decryptor,
|
decryptor,
|
||||||
wtx.vjoinsplit[i].ciphertexts[j],
|
wtx.vjoinsplit[i].ciphertexts[j],
|
||||||
wtx.vjoinsplit[i].ephemeralKey,
|
wtx.vjoinsplit[i].ephemeralKey,
|
||||||
hSig,
|
hSig,
|
||||||
(unsigned char) j);
|
(unsigned char) j);
|
||||||
|
|
||||||
outEntries.push_back(CNotePlaintextEntry{jsop, pa, plaintext});
|
outEntries.push_back(CSproutNotePlaintextEntry{jsop, pa, plaintext});
|
||||||
|
|
||||||
} catch (const note_decryption_failed &err) {
|
} catch (const note_decryption_failed &err) {
|
||||||
// Couldn't decrypt with this spending key
|
// Couldn't decrypt with this spending key
|
||||||
@@ -3809,7 +3809,7 @@ void CWallet::GetFilteredNotes(
|
|||||||
|
|
||||||
/* Find unspent notes filtered by payment address, min depth and max depth */
|
/* Find unspent notes filtered by payment address, min depth and max depth */
|
||||||
void CWallet::GetUnspentFilteredNotes(
|
void CWallet::GetUnspentFilteredNotes(
|
||||||
std::vector<CUnspentNotePlaintextEntry>& outEntries,
|
std::vector<CUnspentSproutNotePlaintextEntry>& outEntries,
|
||||||
std::set<PaymentAddress>& filterAddresses,
|
std::set<PaymentAddress>& filterAddresses,
|
||||||
int minDepth,
|
int minDepth,
|
||||||
int maxDepth,
|
int maxDepth,
|
||||||
@@ -3862,14 +3862,14 @@ void CWallet::GetUnspentFilteredNotes(
|
|||||||
// determine amount of funds in the note
|
// determine amount of funds in the note
|
||||||
auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
|
auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
|
||||||
try {
|
try {
|
||||||
NotePlaintext plaintext = NotePlaintext::decrypt(
|
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
|
||||||
decryptor,
|
decryptor,
|
||||||
wtx.vjoinsplit[i].ciphertexts[j],
|
wtx.vjoinsplit[i].ciphertexts[j],
|
||||||
wtx.vjoinsplit[i].ephemeralKey,
|
wtx.vjoinsplit[i].ephemeralKey,
|
||||||
hSig,
|
hSig,
|
||||||
(unsigned char) j);
|
(unsigned char) j);
|
||||||
|
|
||||||
outEntries.push_back(CUnspentNotePlaintextEntry{jsop, pa, plaintext, wtx.GetDepthInMainChain()});
|
outEntries.push_back(CUnspentSproutNotePlaintextEntry{jsop, pa, plaintext, wtx.GetDepthInMainChain()});
|
||||||
|
|
||||||
} catch (const note_decryption_failed &err) {
|
} catch (const note_decryption_failed &err) {
|
||||||
// Couldn't decrypt with this spending key
|
// Couldn't decrypt with this spending key
|
||||||
|
|||||||
@@ -265,18 +265,18 @@ public:
|
|||||||
typedef std::map<JSOutPoint, CNoteData> mapNoteData_t;
|
typedef std::map<JSOutPoint, CNoteData> mapNoteData_t;
|
||||||
|
|
||||||
/** Decrypted note and its location in a transaction. */
|
/** Decrypted note and its location in a transaction. */
|
||||||
struct CNotePlaintextEntry
|
struct CSproutNotePlaintextEntry
|
||||||
{
|
{
|
||||||
JSOutPoint jsop;
|
JSOutPoint jsop;
|
||||||
libzcash::PaymentAddress address;
|
libzcash::PaymentAddress address;
|
||||||
libzcash::NotePlaintext plaintext;
|
libzcash::SproutNotePlaintext plaintext;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Decrypted note, location in a transaction, and confirmation height. */
|
/** Decrypted note, location in a transaction, and confirmation height. */
|
||||||
struct CUnspentNotePlaintextEntry {
|
struct CUnspentSproutNotePlaintextEntry {
|
||||||
JSOutPoint jsop;
|
JSOutPoint jsop;
|
||||||
libzcash::PaymentAddress address;
|
libzcash::PaymentAddress address;
|
||||||
libzcash::NotePlaintext plaintext;
|
libzcash::SproutNotePlaintext plaintext;
|
||||||
int nHeight;
|
int nHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1139,21 +1139,21 @@ public:
|
|||||||
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
|
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
|
||||||
|
|
||||||
/* Find notes filtered by payment address, min depth, ability to spend */
|
/* Find notes filtered by payment address, min depth, ability to spend */
|
||||||
void GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries,
|
void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry> & outEntries,
|
||||||
std::string address,
|
std::string address,
|
||||||
int minDepth=1,
|
int minDepth=1,
|
||||||
bool ignoreSpent=true,
|
bool ignoreSpent=true,
|
||||||
bool ignoreUnspendable=true);
|
bool ignoreUnspendable=true);
|
||||||
|
|
||||||
/* Find notes filtered by payment addresses, min depth, ability to spend */
|
/* Find notes filtered by payment addresses, min depth, ability to spend */
|
||||||
void GetFilteredNotes(std::vector<CNotePlaintextEntry>& outEntries,
|
void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry>& outEntries,
|
||||||
std::set<libzcash::PaymentAddress>& filterAddresses,
|
std::set<libzcash::PaymentAddress>& filterAddresses,
|
||||||
int minDepth=1,
|
int minDepth=1,
|
||||||
bool ignoreSpent=true,
|
bool ignoreSpent=true,
|
||||||
bool ignoreUnspendable=true);
|
bool ignoreUnspendable=true);
|
||||||
|
|
||||||
/* Find unspent notes filtered by payment address, min depth and max depth */
|
/* Find unspent notes filtered by payment address, min depth and max depth */
|
||||||
void GetUnspentFilteredNotes(std::vector<CUnspentNotePlaintextEntry>& outEntries,
|
void GetUnspentFilteredNotes(std::vector<CUnspentSproutNotePlaintextEntry>& outEntries,
|
||||||
std::set<libzcash::PaymentAddress>& filterAddresses,
|
std::set<libzcash::PaymentAddress>& filterAddresses,
|
||||||
int minDepth=1,
|
int minDepth=1,
|
||||||
int maxDepth=INT_MAX,
|
int maxDepth=INT_MAX,
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ public:
|
|||||||
ZCProof prove(
|
ZCProof prove(
|
||||||
const boost::array<JSInput, NumInputs>& inputs,
|
const boost::array<JSInput, NumInputs>& inputs,
|
||||||
const boost::array<JSOutput, NumOutputs>& outputs,
|
const boost::array<JSOutput, NumOutputs>& outputs,
|
||||||
boost::array<Note, NumOutputs>& out_notes,
|
boost::array<SproutNote, NumOutputs>& out_notes,
|
||||||
boost::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
boost::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
||||||
uint256& out_ephemeralKey,
|
uint256& out_ephemeralKey,
|
||||||
const uint256& pubKeyHash,
|
const uint256& pubKeyHash,
|
||||||
@@ -168,7 +168,7 @@ public:
|
|||||||
// Sanity checks of input
|
// Sanity checks of input
|
||||||
{
|
{
|
||||||
// If note has nonzero value
|
// If note has nonzero value
|
||||||
if (inputs[i].note.value != 0) {
|
if (inputs[i].note.value() != 0) {
|
||||||
// The witness root must equal the input root.
|
// The witness root must equal the input root.
|
||||||
if (inputs[i].witness.root() != rt) {
|
if (inputs[i].witness.root() != rt) {
|
||||||
throw std::invalid_argument("joinsplit not anchored to the correct root");
|
throw std::invalid_argument("joinsplit not anchored to the correct root");
|
||||||
@@ -186,11 +186,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Balance must be sensical
|
// Balance must be sensical
|
||||||
if (inputs[i].note.value > MAX_MONEY) {
|
if (inputs[i].note.value() > MAX_MONEY) {
|
||||||
throw std::invalid_argument("nonsensical input note value");
|
throw std::invalid_argument("nonsensical input note value");
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs_value += inputs[i].note.value;
|
lhs_value += inputs[i].note.value();
|
||||||
|
|
||||||
if (lhs_value > MAX_MONEY) {
|
if (lhs_value > MAX_MONEY) {
|
||||||
throw std::invalid_argument("nonsensical left hand size of joinsplit balance");
|
throw std::invalid_argument("nonsensical left hand size of joinsplit balance");
|
||||||
@@ -246,7 +246,7 @@ public:
|
|||||||
ZCNoteEncryption encryptor(h_sig);
|
ZCNoteEncryption encryptor(h_sig);
|
||||||
|
|
||||||
for (size_t i = 0; i < NumOutputs; i++) {
|
for (size_t i = 0; i < NumOutputs; i++) {
|
||||||
NotePlaintext pt(out_notes[i], outputs[i].memo);
|
SproutNotePlaintext pt(out_notes[i], outputs[i].memo);
|
||||||
|
|
||||||
out_ciphertexts[i] = pt.encrypt(encryptor, outputs[i].addr.pk_enc);
|
out_ciphertexts[i] = pt.encrypt(encryptor, outputs[i].addr.pk_enc);
|
||||||
}
|
}
|
||||||
@@ -364,10 +364,10 @@ uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Note JSOutput::note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const {
|
SproutNote JSOutput::note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const {
|
||||||
uint256 rho = PRF_rho(phi, i, h_sig);
|
uint256 rho = PRF_rho(phi, i, h_sig);
|
||||||
|
|
||||||
return Note(addr.a_pk, value, rho, r);
|
return SproutNote(addr.a_pk, value, rho, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) {
|
JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) {
|
||||||
@@ -377,7 +377,7 @@ JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) {
|
|||||||
|
|
||||||
JSInput::JSInput() : witness(ZCIncrementalMerkleTree().witness()),
|
JSInput::JSInput() : witness(ZCIncrementalMerkleTree().witness()),
|
||||||
key(SpendingKey::random()) {
|
key(SpendingKey::random()) {
|
||||||
note = Note(key.address().a_pk, 0, random_uint256(), random_uint256());
|
note = SproutNote(key.address().a_pk, 0, random_uint256(), random_uint256());
|
||||||
ZCIncrementalMerkleTree dummy_tree;
|
ZCIncrementalMerkleTree dummy_tree;
|
||||||
dummy_tree.append(note.cm());
|
dummy_tree.append(note.cm());
|
||||||
witness = dummy_tree.witness();
|
witness = dummy_tree.witness();
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ namespace libzcash {
|
|||||||
class JSInput {
|
class JSInput {
|
||||||
public:
|
public:
|
||||||
ZCIncrementalWitness witness;
|
ZCIncrementalWitness witness;
|
||||||
Note note;
|
SproutNote note;
|
||||||
SpendingKey key;
|
SpendingKey key;
|
||||||
|
|
||||||
JSInput();
|
JSInput();
|
||||||
JSInput(ZCIncrementalWitness witness,
|
JSInput(ZCIncrementalWitness witness,
|
||||||
Note note,
|
SproutNote note,
|
||||||
SpendingKey key) : witness(witness), note(note), key(key) { }
|
SpendingKey key) : witness(witness), note(note), key(key) { }
|
||||||
|
|
||||||
uint256 nullifier() const {
|
uint256 nullifier() const {
|
||||||
@@ -40,7 +40,7 @@ public:
|
|||||||
JSOutput();
|
JSOutput();
|
||||||
JSOutput(PaymentAddress addr, uint64_t value) : addr(addr), value(value) { }
|
JSOutput(PaymentAddress addr, uint64_t value) : addr(addr), value(value) { }
|
||||||
|
|
||||||
Note note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const;
|
SproutNote note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t NumInputs, size_t NumOutputs>
|
template<size_t NumInputs, size_t NumOutputs>
|
||||||
@@ -62,7 +62,7 @@ public:
|
|||||||
virtual ZCProof prove(
|
virtual ZCProof prove(
|
||||||
const boost::array<JSInput, NumInputs>& inputs,
|
const boost::array<JSInput, NumInputs>& inputs,
|
||||||
const boost::array<JSOutput, NumOutputs>& outputs,
|
const boost::array<JSOutput, NumOutputs>& outputs,
|
||||||
boost::array<Note, NumOutputs>& out_notes,
|
boost::array<SproutNote, NumOutputs>& out_notes,
|
||||||
boost::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
boost::array<ZCNoteEncryption::Ciphertext, NumOutputs>& out_ciphertexts,
|
||||||
uint256& out_ephemeralKey,
|
uint256& out_ephemeralKey,
|
||||||
const uint256& pubKeyHash,
|
const uint256& pubKeyHash,
|
||||||
|
|||||||
@@ -9,21 +9,20 @@
|
|||||||
|
|
||||||
namespace libzcash {
|
namespace libzcash {
|
||||||
|
|
||||||
Note::Note() {
|
SproutNote::SproutNote() {
|
||||||
a_pk = random_uint256();
|
a_pk = random_uint256();
|
||||||
rho = random_uint256();
|
rho = random_uint256();
|
||||||
r = random_uint256();
|
r = random_uint256();
|
||||||
value = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 Note::cm() const {
|
uint256 SproutNote::cm() const {
|
||||||
unsigned char discriminant = 0xb0;
|
unsigned char discriminant = 0xb0;
|
||||||
|
|
||||||
CSHA256 hasher;
|
CSHA256 hasher;
|
||||||
hasher.Write(&discriminant, 1);
|
hasher.Write(&discriminant, 1);
|
||||||
hasher.Write(a_pk.begin(), 32);
|
hasher.Write(a_pk.begin(), 32);
|
||||||
|
|
||||||
auto value_vec = convertIntToVectorLE(value);
|
auto value_vec = convertIntToVectorLE(value_);
|
||||||
|
|
||||||
hasher.Write(&value_vec[0], value_vec.size());
|
hasher.Write(&value_vec[0], value_vec.size());
|
||||||
hasher.Write(rho.begin(), 32);
|
hasher.Write(rho.begin(), 32);
|
||||||
@@ -35,25 +34,24 @@ uint256 Note::cm() const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 Note::nullifier(const SpendingKey& a_sk) const {
|
uint256 SproutNote::nullifier(const SpendingKey& a_sk) const {
|
||||||
return PRF_nf(a_sk, rho);
|
return PRF_nf(a_sk, rho);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotePlaintext::NotePlaintext(
|
SproutNotePlaintext::SproutNotePlaintext(
|
||||||
const Note& note,
|
const SproutNote& note,
|
||||||
boost::array<unsigned char, ZC_MEMO_SIZE> memo) : memo(memo)
|
boost::array<unsigned char, ZC_MEMO_SIZE> memo) : BaseNotePlaintext(note, memo)
|
||||||
{
|
{
|
||||||
value = note.value;
|
|
||||||
rho = note.rho;
|
rho = note.rho;
|
||||||
r = note.r;
|
r = note.r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Note NotePlaintext::note(const PaymentAddress& addr) const
|
SproutNote SproutNotePlaintext::note(const PaymentAddress& addr) const
|
||||||
{
|
{
|
||||||
return Note(addr.a_pk, value, rho, r);
|
return SproutNote(addr.a_pk, value_, rho, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotePlaintext NotePlaintext::decrypt(const ZCNoteDecryption& decryptor,
|
SproutNotePlaintext SproutNotePlaintext::decrypt(const ZCNoteDecryption& decryptor,
|
||||||
const ZCNoteDecryption::Ciphertext& ciphertext,
|
const ZCNoteDecryption::Ciphertext& ciphertext,
|
||||||
const uint256& ephemeralKey,
|
const uint256& ephemeralKey,
|
||||||
const uint256& h_sig,
|
const uint256& h_sig,
|
||||||
@@ -65,7 +63,7 @@ NotePlaintext NotePlaintext::decrypt(const ZCNoteDecryption& decryptor,
|
|||||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ss << plaintext;
|
ss << plaintext;
|
||||||
|
|
||||||
NotePlaintext ret;
|
SproutNotePlaintext ret;
|
||||||
ss >> ret;
|
ss >> ret;
|
||||||
|
|
||||||
assert(ss.size() == 0);
|
assert(ss.size() == 0);
|
||||||
@@ -73,7 +71,7 @@ NotePlaintext NotePlaintext::decrypt(const ZCNoteDecryption& decryptor,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZCNoteEncryption::Ciphertext NotePlaintext::encrypt(ZCNoteEncryption& encryptor,
|
ZCNoteEncryption::Ciphertext SproutNotePlaintext::encrypt(ZCNoteEncryption& encryptor,
|
||||||
const uint256& pk_enc
|
const uint256& pk_enc
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,34 +8,62 @@
|
|||||||
|
|
||||||
namespace libzcash {
|
namespace libzcash {
|
||||||
|
|
||||||
class Note {
|
class BaseNote {
|
||||||
|
protected:
|
||||||
|
uint64_t value_ = 0;
|
||||||
|
public:
|
||||||
|
BaseNote() {}
|
||||||
|
BaseNote(uint64_t value) : value_(value) {};
|
||||||
|
virtual ~BaseNote() {};
|
||||||
|
|
||||||
|
virtual uint256 cm() const {};
|
||||||
|
inline uint64_t value() const { return value_; };
|
||||||
|
};
|
||||||
|
|
||||||
|
class SproutNote : public BaseNote {
|
||||||
public:
|
public:
|
||||||
uint256 a_pk;
|
uint256 a_pk;
|
||||||
uint64_t value;
|
|
||||||
uint256 rho;
|
uint256 rho;
|
||||||
uint256 r;
|
uint256 r;
|
||||||
|
|
||||||
Note(uint256 a_pk, uint64_t value, uint256 rho, uint256 r)
|
SproutNote(uint256 a_pk, uint64_t value, uint256 rho, uint256 r)
|
||||||
: a_pk(a_pk), value(value), rho(rho), r(r) {}
|
: BaseNote(value), a_pk(a_pk), rho(rho), r(r) {}
|
||||||
|
|
||||||
Note();
|
SproutNote();
|
||||||
|
|
||||||
|
virtual ~SproutNote() {};
|
||||||
|
|
||||||
|
virtual uint256 cm() const override;
|
||||||
|
|
||||||
uint256 cm() const;
|
|
||||||
uint256 nullifier(const SpendingKey& a_sk) const;
|
uint256 nullifier(const SpendingKey& a_sk) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NotePlaintext {
|
class BaseNotePlaintext {
|
||||||
|
protected:
|
||||||
|
uint64_t value_ = 0;
|
||||||
|
boost::array<unsigned char, ZC_MEMO_SIZE> memo_;
|
||||||
|
public:
|
||||||
|
BaseNotePlaintext() {}
|
||||||
|
BaseNotePlaintext(const BaseNote& note, boost::array<unsigned char, ZC_MEMO_SIZE> memo)
|
||||||
|
: value_(note.value()), memo_(memo) {}
|
||||||
|
virtual ~BaseNotePlaintext() {}
|
||||||
|
|
||||||
|
inline uint64_t value() const { return value_; }
|
||||||
|
inline boost::array<unsigned char, ZC_MEMO_SIZE> memo() const { return memo_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class SproutNotePlaintext : public BaseNotePlaintext {
|
||||||
public:
|
public:
|
||||||
uint64_t value = 0;
|
|
||||||
uint256 rho;
|
uint256 rho;
|
||||||
uint256 r;
|
uint256 r;
|
||||||
boost::array<unsigned char, ZC_MEMO_SIZE> memo;
|
|
||||||
|
|
||||||
NotePlaintext() {}
|
SproutNotePlaintext() {}
|
||||||
|
|
||||||
NotePlaintext(const Note& note, boost::array<unsigned char, ZC_MEMO_SIZE> memo);
|
SproutNotePlaintext(const SproutNote& note, boost::array<unsigned char, ZC_MEMO_SIZE> memo);
|
||||||
|
|
||||||
Note note(const PaymentAddress& addr) const;
|
SproutNote note(const PaymentAddress& addr) const;
|
||||||
|
|
||||||
|
virtual ~SproutNotePlaintext() {}
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
@@ -45,16 +73,16 @@ public:
|
|||||||
READWRITE(leadingByte);
|
READWRITE(leadingByte);
|
||||||
|
|
||||||
if (leadingByte != 0x00) {
|
if (leadingByte != 0x00) {
|
||||||
throw std::ios_base::failure("lead byte of NotePlaintext is not recognized");
|
throw std::ios_base::failure("lead byte of SproutNotePlaintext is not recognized");
|
||||||
}
|
}
|
||||||
|
|
||||||
READWRITE(value);
|
READWRITE(value_);
|
||||||
READWRITE(rho);
|
READWRITE(rho);
|
||||||
READWRITE(r);
|
READWRITE(r);
|
||||||
READWRITE(memo);
|
READWRITE(memo_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NotePlaintext decrypt(const ZCNoteDecryption& decryptor,
|
static SproutNotePlaintext decrypt(const ZCNoteDecryption& decryptor,
|
||||||
const ZCNoteDecryption::Ciphertext& ciphertext,
|
const ZCNoteDecryption::Ciphertext& ciphertext,
|
||||||
const uint256& ephemeralKey,
|
const uint256& ephemeralKey,
|
||||||
const uint256& h_sig,
|
const uint256& h_sig,
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public:
|
|||||||
const uint256& rt,
|
const uint256& rt,
|
||||||
const uint256& h_sig,
|
const uint256& h_sig,
|
||||||
const boost::array<JSInput, NumInputs>& inputs,
|
const boost::array<JSInput, NumInputs>& inputs,
|
||||||
const boost::array<Note, NumOutputs>& outputs,
|
const boost::array<SproutNote, NumOutputs>& outputs,
|
||||||
uint64_t vpub_old,
|
uint64_t vpub_old,
|
||||||
uint64_t vpub_new
|
uint64_t vpub_new
|
||||||
) {
|
) {
|
||||||
@@ -222,7 +222,7 @@ public:
|
|||||||
// Witness total_uint64 bits
|
// Witness total_uint64 bits
|
||||||
uint64_t left_side_acc = vpub_old;
|
uint64_t left_side_acc = vpub_old;
|
||||||
for (size_t i = 0; i < NumInputs; i++) {
|
for (size_t i = 0; i < NumInputs; i++) {
|
||||||
left_side_acc += inputs[i].note.value;
|
left_side_acc += inputs[i].note.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
zk_total_uint64.fill_with_bits(
|
zk_total_uint64.fill_with_bits(
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ public:
|
|||||||
r->generate_r1cs_constraints();
|
r->generate_r1cs_constraints();
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_r1cs_witness(const Note& note) {
|
void generate_r1cs_witness(const SproutNote& note) {
|
||||||
r->bits.fill_with_bits(this->pb, uint256_to_bool_vector(note.r));
|
r->bits.fill_with_bits(this->pb, uint256_to_bool_vector(note.r));
|
||||||
value.fill_with_bits(this->pb, uint64_to_bool_vector(note.value));
|
value.fill_with_bits(this->pb, uint64_to_bool_vector(note.value()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ public:
|
|||||||
void generate_r1cs_witness(
|
void generate_r1cs_witness(
|
||||||
const MerklePath& path,
|
const MerklePath& path,
|
||||||
const SpendingKey& key,
|
const SpendingKey& key,
|
||||||
const Note& note
|
const SproutNote& note
|
||||||
) {
|
) {
|
||||||
note_gadget<FieldT>::generate_r1cs_witness(note);
|
note_gadget<FieldT>::generate_r1cs_witness(note);
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Set enforce flag for nonzero input value
|
// Set enforce flag for nonzero input value
|
||||||
this->pb.val(value_enforce) = (note.value != 0) ? FieldT::one() : FieldT::zero();
|
this->pb.val(value_enforce) = (note.value() != 0) ? FieldT::one() : FieldT::zero();
|
||||||
|
|
||||||
// Witness merkle tree authentication path
|
// Witness merkle tree authentication path
|
||||||
witness_input->generate_r1cs_witness(path);
|
witness_input->generate_r1cs_witness(path);
|
||||||
@@ -222,7 +222,7 @@ public:
|
|||||||
commit_to_outputs->generate_r1cs_constraints();
|
commit_to_outputs->generate_r1cs_constraints();
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_r1cs_witness(const Note& note) {
|
void generate_r1cs_witness(const SproutNote& note) {
|
||||||
note_gadget<FieldT>::generate_r1cs_witness(note);
|
note_gadget<FieldT>::generate_r1cs_witness(note);
|
||||||
|
|
||||||
prevent_faerie_gold->generate_r1cs_witness();
|
prevent_faerie_gold->generate_r1cs_witness();
|
||||||
|
|||||||
Reference in New Issue
Block a user