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:
Homu
2018-05-02 08:07:35 -07:00
24 changed files with 206 additions and 148 deletions

View File

@@ -455,22 +455,22 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
ZCNoteDecryption decryptor(changeKey.receiving_key());
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
try {
NotePlaintext plaintext = NotePlaintext::decrypt(
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
decryptor,
prevJoinSplit.ciphertexts[changeOutputIndex],
prevJoinSplit.ephemeralKey,
hSig,
(unsigned char)changeOutputIndex);
Note note = plaintext.note(changeAddress);
SproutNote note = plaintext.note(changeAddress);
info.notes.push_back(note);
info.zkeys.push_back(changeKey);
jsInputValue += plaintext.value;
jsInputValue += plaintext.value();
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
getId(),
FormatMoney(plaintext.value));
FormatMoney(plaintext.value()));
} catch (const std::exception& e) {
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
//
std::vector<Note> vInputNotes;
std::vector<SproutNote> vInputNotes;
std::vector<SpendingKey> vInputZKeys;
std::vector<JSOutPoint> vOutPoints;
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
@@ -490,7 +490,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
MergeToAddressInputNote t = zInputsDeque.front();
JSOutPoint jso = std::get<0>(t);
Note note = std::get<1>(t);
SproutNote note = std::get<1>(t);
CAmount noteFunds = std::get<2>(t);
SpendingKey zkey = std::get<3>(t);
zInputsDeque.pop_front();
@@ -753,7 +753,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
getId(),
tx_.vjoinsplit.size(),
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));
// Generate the proof, this can take over a minute.

View File

@@ -28,7 +28,7 @@ using namespace libzcash;
typedef std::tuple<COutPoint, CAmount> MergeToAddressInputUTXO;
// 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)
typedef std::tuple<std::string, std::string> MergeToAddressRecipient;
@@ -37,7 +37,7 @@ typedef std::tuple<std::string, std::string> MergeToAddressRecipient;
struct MergeToAddressJSInfo {
std::vector<JSInput> vjsin;
std::vector<JSOutput> vjsout;
std::vector<Note> notes;
std::vector<SproutNote> notes;
std::vector<SpendingKey> zkeys;
CAmount vpub_old = 0;
CAmount vpub_new = 0;

View File

@@ -571,21 +571,21 @@ bool AsyncRPCOperation_sendmany::main_impl() {
ZCNoteDecryption decryptor(spendingkey_.receiving_key());
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
try {
NotePlaintext plaintext = NotePlaintext::decrypt(
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
decryptor,
prevJoinSplit.ciphertexts[changeOutputIndex],
prevJoinSplit.ephemeralKey,
hSig,
(unsigned char) changeOutputIndex);
Note note = plaintext.note(frompaymentaddress_);
SproutNote note = plaintext.note(frompaymentaddress_);
info.notes.push_back(note);
jsInputValue += plaintext.value;
jsInputValue += plaintext.value();
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
getId(),
FormatMoney(plaintext.value)
FormatMoney(plaintext.value())
);
} catch (const std::exception& e) {
@@ -597,7 +597,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
//
// Consume spendable non-change notes
//
std::vector<Note> vInputNotes;
std::vector<SproutNote> vInputNotes;
std::vector<JSOutPoint> vOutPoints;
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
uint256 inputAnchor;
@@ -605,7 +605,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
SendManyInputJSOP t = zInputsDeque.front();
JSOutPoint jso = std::get<0>(t);
Note note = std::get<1>(t);
SproutNote note = std::get<1>(t);
CAmount noteFunds = std::get<2>(t);
zInputsDeque.pop_front();
@@ -877,21 +877,21 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) {
bool AsyncRPCOperation_sendmany::find_unspent_notes() {
std::vector<CNotePlaintextEntry> entries;
std::vector<CSproutNotePlaintextEntry> entries;
{
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->GetFilteredNotes(entries, fromaddress_, mindepth_);
}
for (CNotePlaintextEntry & entry : entries) {
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());
for (CSproutNotePlaintextEntry & entry : entries) {
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());
LogPrint("zrpcunsafe", "%s: found unspent note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n",
getId(),
entry.jsop.hash.ToString().substr(0, 10),
entry.jsop.js,
int(entry.jsop.n), // uint8_t
FormatMoney(entry.plaintext.value),
FormatMoney(entry.plaintext.value()),
HexStr(data).substr(0, 10)
);
}
@@ -968,7 +968,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
getId(),
tx_.vjoinsplit.size(),
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)
);

View File

@@ -31,14 +31,14 @@ typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
typedef std::tuple<uint256, int, CAmount, bool> SendManyInputUTXO;
// 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.
struct AsyncJoinSplitInfo
{
std::vector<JSInput> vjsin;
std::vector<JSOutput> vjsout;
std::vector<Note> notes;
std::vector<SproutNote> notes;
CAmount vpub_old = 0;
CAmount vpub_new = 0;
};

View File

@@ -341,7 +341,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
getId(),
tx_.vjoinsplit.size(),
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)
);

View File

@@ -72,13 +72,13 @@ CWalletTx GetValidReceive(const libzcash::SpendingKey& sk, CAmount value, bool r
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) {
return GetNote(*params, sk, tx, js, n);
}
CWalletTx GetValidSpend(const libzcash::SpendingKey& sk,
const libzcash::Note& note, CAmount value) {
const libzcash::SproutNote& note, CAmount value) {
return GetValidSpend(*params, sk, note, value);
}
@@ -155,7 +155,7 @@ TEST(wallet_tests, find_unspent_notes) {
EXPECT_FALSE(wallet.IsSpent(nullifier));
// 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);
EXPECT_EQ(0, entries.size());
entries.clear();

View File

@@ -274,16 +274,16 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
CDataStream ssPlain(SER_NETWORK, PROTOCOL_VERSION);
ssPlain << plaintext;
NotePlaintext npt;
SproutNotePlaintext 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("value", ValueFromAmount(npt.value)));
o.push_back(Pair("value", ValueFromAmount(npt.value())));
// Check the blockchain commitment matches decrypted note commitment
uint256 cm_blockchain = jsdesc.commitments[pd.payload.n];
Note note = npt.note(zaddr);
SproutNote note = npt.note(zaddr);
uint256 cm_decrypted = note.cm();
bool cm_match = (cm_decrypted == cm_blockchain);
o.push_back(Pair("commitmentMatch", cm_match));

View File

@@ -2537,9 +2537,9 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
UniValue results(UniValue::VARR);
if (zaddrs.size() > 0) {
std::vector<CUnspentNotePlaintextEntry> entries;
std::vector<CUnspentSproutNotePlaintextEntry> entries;
pwalletMain->GetUnspentFilteredNotes(entries, zaddrs, nMinDepth, nMaxDepth, !fIncludeWatchonly);
for (CUnspentNotePlaintextEntry & entry : entries) {
for (CUnspentSproutNotePlaintextEntry & entry : entries) {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
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("spendable", pwalletMain->HaveSpendingKey(entry.address)));
obj.push_back(Pair("address", CZCPaymentAddress(entry.address).ToString()));
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value))));
std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end());
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
obj.push_back(Pair("memo", HexStr(data)));
results.push_back(obj);
}
@@ -2807,7 +2807,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
ZCNoteDecryption decryptor(k.receiving_key());
NotePlaintext npt = NotePlaintext::decrypt(
SproutNotePlaintext npt = SproutNotePlaintext::decrypt(
decryptor,
ct,
epk,
@@ -2815,7 +2815,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
nonce
);
PaymentAddress payment_addr = k.address();
Note decrypted_note = npt.note(payment_addr);
SproutNote decrypted_note = npt.note(payment_addr);
assert(pwalletMain != NULL);
std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
@@ -2831,7 +2831,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
ss << npt;
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("exists", (bool) witnesses[0]));
return result;
@@ -2889,7 +2889,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
std::vector<JSInput> vjsin;
std::vector<JSOutput> vjsout;
std::vector<Note> notes;
std::vector<SproutNote> notes;
std::vector<SpendingKey> keys;
std::vector<uint256> commitments;
@@ -2899,7 +2899,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
keys.push_back(k);
NotePlaintext npt;
SproutNotePlaintext npt;
{
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();
Note note = npt.note(addr);
SproutNote note = npt.note(addr);
notes.push_back(note);
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 balance = 0;
std::vector<CNotePlaintextEntry> entries;
std::vector<CSproutNotePlaintextEntry> entries;
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->GetFilteredNotes(entries, address, minDepth, true, ignoreUnspendable);
for (auto & entry : entries) {
balance += CAmount(entry.plaintext.value);
balance += CAmount(entry.plaintext.value());
}
return balance;
}
@@ -3233,13 +3233,13 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
UniValue result(UniValue::VARR);
std::vector<CNotePlaintextEntry> entries;
std::vector<CSproutNotePlaintextEntry> entries;
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
for (CNotePlaintextEntry & entry : entries) {
for (CSproutNotePlaintextEntry & entry : entries) {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value))));
std::string data(entry.plaintext.memo.begin(), entry.plaintext.memo.end());
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
obj.push_back(Pair("memo", HexStr(data)));
// (txid, jsindex, jsoutindex) is needed to globally identify a note
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) {
// Get available notes
std::vector<CNotePlaintextEntry> entries;
std::vector<CSproutNotePlaintextEntry> entries;
pwalletMain->GetFilteredNotes(entries, zaddrs);
// Find unspent notes and update estimated size
for (CNotePlaintextEntry& entry : entries) {
for (CSproutNotePlaintextEntry& entry : entries) {
noteCounter++;
CAmount nValue = entry.plaintext.value;
CAmount nValue = entry.plaintext.value();
if (!maxedOutNotesFlag) {
// If we haven't added any notes yet and the merge is to a

View File

@@ -1264,7 +1264,7 @@ boost::optional<uint256> CWallet::GetNoteNullifier(const JSDescription& jsdesc,
uint8_t n) const
{
boost::optional<uint256> ret;
auto note_pt = libzcash::NotePlaintext::decrypt(
auto note_pt = libzcash::SproutNotePlaintext::decrypt(
dec,
jsdesc.ciphertexts[n],
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.
* 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;
@@ -3728,7 +3728,7 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
* These notes are decrypted and added to the output parameter vector, outEntries.
*/
void CWallet::GetFilteredNotes(
std::vector<CNotePlaintextEntry>& outEntries,
std::vector<CSproutNotePlaintextEntry>& outEntries,
std::set<PaymentAddress>& filterAddresses,
int minDepth,
bool ignoreSpent,
@@ -3786,14 +3786,14 @@ void CWallet::GetFilteredNotes(
// determine amount of funds in the note
auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
try {
NotePlaintext plaintext = NotePlaintext::decrypt(
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
decryptor,
wtx.vjoinsplit[i].ciphertexts[j],
wtx.vjoinsplit[i].ephemeralKey,
hSig,
(unsigned char) j);
outEntries.push_back(CNotePlaintextEntry{jsop, pa, plaintext});
outEntries.push_back(CSproutNotePlaintextEntry{jsop, pa, plaintext});
} catch (const note_decryption_failed &err) {
// 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 */
void CWallet::GetUnspentFilteredNotes(
std::vector<CUnspentNotePlaintextEntry>& outEntries,
std::vector<CUnspentSproutNotePlaintextEntry>& outEntries,
std::set<PaymentAddress>& filterAddresses,
int minDepth,
int maxDepth,
@@ -3862,14 +3862,14 @@ void CWallet::GetUnspentFilteredNotes(
// determine amount of funds in the note
auto hSig = wtx.vjoinsplit[i].h_sig(*pzcashParams, wtx.joinSplitPubKey);
try {
NotePlaintext plaintext = NotePlaintext::decrypt(
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
decryptor,
wtx.vjoinsplit[i].ciphertexts[j],
wtx.vjoinsplit[i].ephemeralKey,
hSig,
(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) {
// Couldn't decrypt with this spending key

View File

@@ -265,18 +265,18 @@ public:
typedef std::map<JSOutPoint, CNoteData> mapNoteData_t;
/** Decrypted note and its location in a transaction. */
struct CNotePlaintextEntry
struct CSproutNotePlaintextEntry
{
JSOutPoint jsop;
libzcash::PaymentAddress address;
libzcash::NotePlaintext plaintext;
libzcash::SproutNotePlaintext plaintext;
};
/** Decrypted note, location in a transaction, and confirmation height. */
struct CUnspentNotePlaintextEntry {
struct CUnspentSproutNotePlaintextEntry {
JSOutPoint jsop;
libzcash::PaymentAddress address;
libzcash::NotePlaintext plaintext;
libzcash::SproutNotePlaintext plaintext;
int nHeight;
};
@@ -1139,21 +1139,21 @@ public:
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
/* 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,
int minDepth=1,
bool ignoreSpent=true,
bool ignoreUnspendable=true);
/* 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,
int minDepth=1,
bool ignoreSpent=true,
bool ignoreUnspendable=true);
/* 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,
int minDepth=1,
int maxDepth=INT_MAX,