From 86a98587a1d1fa7c89f77ef213416eed7b5eb1b2 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 10:14:52 -0400 Subject: [PATCH] desprout --- src/consensus/upgrades.cpp | 1 + src/serialize.h | 1 + src/wallet/asyncrpcoperation_mergetoaddress.h | 49 ---------- src/wallet/gtest/test_wallet.cpp | 5 - src/wallet/rpcwallet.cpp | 4 +- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 91 ++----------------- src/zcash/Address.hpp | 73 +-------------- src/zcash/JoinSplit.cpp | 18 ---- src/zcash/JoinSplit.hpp | 56 ------------ src/zcash/Note.hpp | 63 +------------ src/zcash/prf.h | 10 +- src/zcash/zip32.h | 3 +- 13 files changed, 24 insertions(+), 352 deletions(-) diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index b75e0c002..984ca377e 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/serialize.h b/src/serialize.h index 3d9c3fae6..9d23b469c 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2014 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index 4876921db..32dbcf015 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -44,29 +44,11 @@ using namespace libzcash; // Input UTXO is a tuple of txid, vout, amount, script typedef std::tuple MergeToAddressInputUTXO; -// Input JSOP is a tuple of JSOutpoint, note, amount, spending key -typedef std::tuple MergeToAddressInputSproutNote; - typedef std::tuple MergeToAddressInputSaplingNote; // A recipient is a tuple of address, memo (optional if zaddr) typedef std::tuple MergeToAddressRecipient; -// Package of info which is passed to perform_joinsplit methods. -struct MergeToAddressJSInfo { - std::vector vjsin; - std::vector vjsout; - std::vector notes; - std::vector zkeys; - CAmount vpub_old = 0; - CAmount vpub_new = 0; -}; - -// A struct to help us track the witness and anchor for a given JSOutPoint -struct MergeToAddressWitnessAnchorData { - boost::optional witness; - uint256 anchor; -}; class AsyncRPCOperation_mergetoaddress : public AsyncRPCOperation { @@ -116,7 +98,6 @@ private: std::unordered_map jsopWitnessAnchorMap; std::vector utxoInputs_; - std::vector sproutNoteInputs_; std::vector saplingNoteInputs_; TransactionBuilder builder_; @@ -125,18 +106,6 @@ private: std::array get_memo_from_hex_string(std::string s); bool main_impl(); - // JoinSplit without any input notes to spend - UniValue perform_joinsplit(MergeToAddressJSInfo&); - - // JoinSplit with input notes to spend (JSOutPoints)) - UniValue perform_joinsplit(MergeToAddressJSInfo&, std::vector&); - - // JoinSplit where you have the witnesses and anchor - UniValue perform_joinsplit( - MergeToAddressJSInfo& info, - std::vector> witnesses, - uint256 anchor); - void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error void lock_utxos(); @@ -180,24 +149,6 @@ public: return delegate->main_impl(); } - UniValue perform_joinsplit(MergeToAddressJSInfo& info) - { - return delegate->perform_joinsplit(info); - } - - UniValue perform_joinsplit(MergeToAddressJSInfo& info, std::vector& v) - { - return delegate->perform_joinsplit(info, v); - } - - UniValue perform_joinsplit( - MergeToAddressJSInfo& info, - std::vector> witnesses, - uint256 anchor) - { - return delegate->perform_joinsplit(info, witnesses, anchor); - } - void sign_send_raw_transaction(UniValue obj) { delegate->sign_send_raw_transaction(obj); diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index 0ad789137..6373b6e9f 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -75,11 +75,6 @@ CWalletTx GetValidReceive(const libzcash::SproutSpendingKey& sk, CAmount value, return GetValidReceive(*params, sk, value, randomInputs, version); } -libzcash::SproutNote GetNote(const libzcash::SproutSpendingKey& sk, - const CTransaction& tx, size_t js, size_t n) { - return GetNote(*params, sk, tx, js, n); -} - CWalletTx GetValidSpend(const libzcash::SproutSpendingKey& sk, const libzcash::SproutNote& note, CAmount value) { return GetValidSpend(*params, sk, note, value); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d3d396bbc..2a451dc12 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3123,7 +3123,7 @@ UniValue getalldata(const UniValue& params, bool fHelp,const CPubKey&) if (wtx.GetDepthInMainChain() < 0) continue; - if (wtx.mapSaplingNoteData.size() == 0 && wtx.mapSproutNoteData.size() == 0 && !wtx.IsTrusted()) + if (wtx.mapSaplingNoteData.size() == 0 && !wtx.IsTrusted()) continue; //Assign Immature @@ -3309,7 +3309,7 @@ UniValue getalldata(const UniValue& params, bool fHelp,const CPubKey&) if (!CheckFinalTx(wtx)) continue; - if (wtx.mapSaplingNoteData.size() == 0 && wtx.mapSproutNoteData.size() == 0 && !wtx.IsTrusted()) + if (wtx.mapSaplingNoteData.size() == 0 && !wtx.IsTrusted()) continue; //Excude transactions with less confirmations than required diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4be804abb..a346a547f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -934,7 +934,7 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO for (std::pair& wtxItem : mapWallet) { nWitnessTxIncrement += 1; - if (wtxItem.second.mapSproutNoteData.empty() && wtxItem.second.mapSaplingNoteData.empty()) + if (wtxItem.second.mapSaplingNoteData.empty()) continue; if (wtxItem.second.GetDepthInMainChain() > 0) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f3526c583..0cd7d8bb6 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -236,82 +236,19 @@ public: std::string ToString() const; }; -class SproutNoteData +class SaplingNoteData { public: - libzcash::SproutPaymentAddress address; - - /** - * Cached note nullifier. May not be set if the wallet was not unlocked when - * this was SproutNoteData was created. If not set, we always assume that the - * note has not been spent. - * - * It's okay to cache the nullifier in the wallet, because we are storing - * the spending key there too, which could be used to derive this. - * If the wallet is encrypted, this means that someone with access to the - * locked wallet cannot spend notes, but can connect received notes to the - * transactions they are spent in. This is the same security semantics as - * for transparent addresses. - */ - boost::optional nullifier; - - /** - * Cached incremental witnesses for spendable Notes. - * Beginning of the list is the most recent witness. - */ - std::list witnesses; - /** * Block height corresponding to the most current witness. * - * When we first create a SproutNoteData in CWallet::FindMySproutNotes, this is set to + * When we first create a SaplingNoteData in CWallet::FindMySaplingNotes, this is set to * -1 as a placeholder. The next time CWallet::ChainTip is called, we can * determine what height the witness cache for this note is valid for (even * if no witnesses were cached), and so can set the correct value in * CWallet::BuildWitnessCache and CWallet::DecrementNoteWitnesses. */ - int witnessHeight; - //In Memory Only - bool witnessRootValidated; - - SproutNoteData() : address(), nullifier(), witnessHeight {-1}, witnessRootValidated {false} { } - SproutNoteData(libzcash::SproutPaymentAddress a) : - address {a}, nullifier(), witnessHeight {-1}, witnessRootValidated {false} { } - SproutNoteData(libzcash::SproutPaymentAddress a, uint256 n) : - address {a}, nullifier {n}, witnessHeight {-1}, witnessRootValidated {false} { } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(address); - READWRITE(nullifier); - READWRITE(witnesses); - READWRITE(witnessHeight); - } - - friend bool operator<(const SproutNoteData& a, const SproutNoteData& b) { - return (a.address < b.address || - (a.address == b.address && a.nullifier < b.nullifier)); - } - - friend bool operator==(const SproutNoteData& a, const SproutNoteData& b) { - return (a.address == b.address && a.nullifier == b.nullifier); - } - - friend bool operator!=(const SproutNoteData& a, const SproutNoteData& b) { - return !(a == b); - } -}; - -class SaplingNoteData -{ -public: - /** - * We initialize the height to -1 for the same reason as we do in SproutNoteData. - * See the comment in that class for a full description. - */ SaplingNoteData() : witnessHeight {-1}, nullifier() { } SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk) : ivk {ivk}, witnessHeight {-1}, nullifier() { } SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk, uint256 n) : ivk {ivk}, witnessHeight {-1}, nullifier(n) { } @@ -347,18 +284,11 @@ public: } }; + +// NOTE: this sprout structure is serialized into wallet.dat, removing it would change wallet.dat format on disk :( typedef std::map mapSproutNoteData_t; typedef std::map mapSaplingNoteData_t; -/** Decrypted note, its location in a transaction, and number of confirmations. */ -struct CSproutNotePlaintextEntry -{ - JSOutPoint jsop; - libzcash::SproutPaymentAddress address; - libzcash::SproutNotePlaintext plaintext; - int confirmations; -}; - /** Sapling note, its location in a transaction, and number of confirmations. */ struct SaplingNoteEntry { @@ -824,7 +754,6 @@ public: protected: - int SproutWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight); int SaplingWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight); /** @@ -848,11 +777,11 @@ protected: try { for (std::pair& wtxItem : mapWallet) { auto wtx = wtxItem.second; - // We skip transactions for which mapSproutNoteData and mapSaplingNoteData - // are empty. This covers transactions that have no Sprout or Sapling data + // We skip transactions for which mapSaplingNoteData + // is empty. This covers transactions that have no Sapling data // (i.e. are purely transparent), as well as shielding and unshielding // transactions in which we only have transparent addresses involved. - if (!(wtx.mapSproutNoteData.empty() && wtx.mapSaplingNoteData.empty())) { + if (!(wtx.mapSaplingNoteData.empty())) { if (!walletdb.WriteTx(wtxItem.first, wtx)) { LogPrintf("SetBestChain(): Failed to write CWalletTx, aborting atomic write\n"); walletdb.TxnAbort(); @@ -1319,8 +1248,7 @@ public: bool LoadCryptedHDSeed(const uint256& seedFp, const std::vector& seed); /* Find notes filtered by payment address, min depth, ability to spend */ - void GetFilteredNotes(std::vector& sproutEntries, - std::vector& saplingEntries, + void GetFilteredNotes(std::vector& saplingEntries, std::string address, int minDepth=1, bool ignoreSpent=true, @@ -1328,8 +1256,7 @@ public: /* Find notes filtered by payment addresses, min depth, max depth, if they are spent, if a spending key is required, and if they are locked */ - void GetFilteredNotes(std::vector& sproutEntries, - std::vector& saplingEntries, + void GetFilteredNotes(std::vector& saplingEntries, std::set& filterAddresses, int minDepth=1, int maxDepth=INT_MAX, diff --git a/src/zcash/Address.hpp b/src/zcash/Address.hpp index 42ee0031b..df9034bce 100644 --- a/src/zcash/Address.hpp +++ b/src/zcash/Address.hpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #ifndef ZC_ADDRESS_H_ #define ZC_ADDRESS_H_ @@ -26,34 +28,6 @@ const size_t SerializedSaplingSpendingKeySize = 32; typedef std::array diversifier_t; -class SproutPaymentAddress { -public: - uint256 a_pk; - uint256 pk_enc; - - SproutPaymentAddress() : a_pk(), pk_enc() { } - SproutPaymentAddress(uint256 a_pk, uint256 pk_enc) : a_pk(a_pk), pk_enc(pk_enc) { } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(a_pk); - READWRITE(pk_enc); - } - - //! Get the 256-bit SHA256d hash of this payment address. - uint256 GetHash() const; - - friend inline bool operator==(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { - return a.a_pk == b.a_pk && a.pk_enc == b.pk_enc; - } - friend inline bool operator<(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { - return (a.a_pk < b.a_pk || - (a.a_pk == b.a_pk && a.pk_enc < b.pk_enc)); - } -}; - class ReceivingKey : public uint256 { public: ReceivingKey() { } @@ -62,45 +36,6 @@ public: uint256 pk_enc() const; }; -class SproutViewingKey { -public: - uint256 a_pk; - ReceivingKey sk_enc; - - SproutViewingKey() : a_pk(), sk_enc() { } - SproutViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(a_pk); - READWRITE(sk_enc); - } - - SproutPaymentAddress address() const; - - friend inline bool operator==(const SproutViewingKey& a, const SproutViewingKey& b) { - return a.a_pk == b.a_pk && a.sk_enc == b.sk_enc; - } - friend inline bool operator<(const SproutViewingKey& a, const SproutViewingKey& b) { - return (a.a_pk < b.a_pk || - (a.a_pk == b.a_pk && a.sk_enc < b.sk_enc)); - } -}; - -class SproutSpendingKey : public uint252 { -public: - SproutSpendingKey() : uint252() { } - SproutSpendingKey(uint252 a_sk) : uint252(a_sk) { } - - static SproutSpendingKey random(); - - ReceivingKey receiving_key() const; - SproutViewingKey viewing_key() const; - SproutPaymentAddress address() const; -}; - //! Sapling functions. class SaplingPaymentAddress { public: @@ -218,8 +153,8 @@ public: SaplingPaymentAddress default_address() const; }; -typedef boost::variant PaymentAddress; -typedef boost::variant ViewingKey; +typedef boost::variant PaymentAddress; +typedef boost::variant ViewingKey; } diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 0a052209a..e71bf25b1 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -246,24 +246,6 @@ uint256 JoinSplit::h_sig( return output; } -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); - - return SproutNote(addr.a_pk, value, rho, r); -} - -JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) { - SproutSpendingKey a_sk = SproutSpendingKey::random(); - addr = a_sk.address(); -} - -JSInput::JSInput() : witness(SproutMerkleTree().witness()), - key(SproutSpendingKey::random()) { - note = SproutNote(key.address().a_pk, 0, random_uint256(), random_uint256()); - SproutMerkleTree dummy_tree; - dummy_tree.append(note.cm()); - witness = dummy_tree.witness(); -} template class JoinSplit; diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index 09e31570f..27df05db0 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -24,69 +24,13 @@ typedef std::array GrothProof; typedef boost::variant SproutProof; class JSInput { -public: - SproutWitness witness; - SproutNote note; - SproutSpendingKey key; - - JSInput(); - JSInput(SproutWitness witness, - SproutNote note, - SproutSpendingKey key) : witness(witness), note(note), key(key) { } - - uint256 nullifier() const { - return note.nullifier(key); - } }; class JSOutput { -public: - SproutPaymentAddress addr; - uint64_t value; - std::array memo = {{0xF6}}; // 0xF6 is invalid UTF8 as per spec, rest of array is 0x00 - - JSOutput(); - JSOutput(SproutPaymentAddress addr, uint64_t value) : addr(addr), value(value) { } - - SproutNote note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const; }; template class JoinSplit { -public: - virtual ~JoinSplit() {} - - static JoinSplit* Prepared(); - - static uint256 h_sig(const uint256& randomSeed, - const std::array& nullifiers, - const uint256& joinSplitPubKey - ); - - // Compute nullifiers, macs, note commitments & encryptions, and SNARK proof - virtual SproutProof prove( - const std::array& inputs, - const std::array& outputs, - std::array& out_notes, - std::array& out_ciphertexts, - uint256& out_ephemeralKey, - const uint256& joinSplitPubKey, - uint256& out_randomSeed, - std::array& out_hmacs, - std::array& out_nullifiers, - std::array& out_commitments, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt, - bool computeProof = true, - // For paymentdisclosure, we need to retrieve the esk. - // Reference as non-const parameter with default value leads to compile error. - // So use pointer for simplicity. - uint256 *out_esk = nullptr - ) = 0; - -protected: - JoinSplit() {} }; } diff --git a/src/zcash/Note.hpp b/src/zcash/Note.hpp index 7d3377306..5b16d95c5 100644 --- a/src/zcash/Note.hpp +++ b/src/zcash/Note.hpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #ifndef ZC_NOTE_H_ #define ZC_NOTE_H_ @@ -22,25 +24,6 @@ public: inline uint64_t value() const { return value_; }; }; -class SproutNote : public BaseNote { -public: - uint256 a_pk; - uint256 rho; - uint256 r; - - SproutNote(uint256 a_pk, uint64_t value, uint256 rho, uint256 r) - : BaseNote(value), a_pk(a_pk), rho(rho), r(r) {} - - SproutNote(); - - virtual ~SproutNote() {}; - - uint256 cm() const; - - uint256 nullifier(const SproutSpendingKey& a_sk) const; -}; - - class SaplingNote : public BaseNote { public: diversifier_t d; @@ -74,48 +57,6 @@ public: inline const std::array & memo() const { return memo_; } }; -class SproutNotePlaintext : public BaseNotePlaintext { -public: - uint256 rho; - uint256 r; - - SproutNotePlaintext() {} - - SproutNotePlaintext(const SproutNote& note, std::array memo); - - SproutNote note(const SproutPaymentAddress& addr) const; - - virtual ~SproutNotePlaintext() {} - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - unsigned char leadingByte = 0x00; - READWRITE(leadingByte); - - if (leadingByte != 0x00) { - throw std::ios_base::failure("lead byte of SproutNotePlaintext is not recognized"); - } - - READWRITE(value_); - READWRITE(rho); - READWRITE(r); - READWRITE(memo_); - } - - static SproutNotePlaintext decrypt(const ZCNoteDecryption& decryptor, - const ZCNoteDecryption::Ciphertext& ciphertext, - const uint256& ephemeralKey, - const uint256& h_sig, - unsigned char nonce - ); - - ZCNoteEncryption::Ciphertext encrypt(ZCNoteEncryption& encryptor, - const uint256& pk_enc - ) const; -}; - typedef std::pair SaplingNotePlaintextEncryptionResult; class SaplingNotePlaintext : public BaseNotePlaintext { diff --git a/src/zcash/prf.h b/src/zcash/prf.h index f666cfa23..adfd7d710 100644 --- a/src/zcash/prf.h +++ b/src/zcash/prf.h @@ -1,5 +1,6 @@ +// Copyright (c) 2019-2020 The Hush developers /* -Zcash uses SHA256Compress as a PRF for various components +Hush uses SHA256Compress as a PRF for various components within the zkSNARK circuit. */ @@ -11,13 +12,6 @@ within the zkSNARK circuit. #include -//! Sprout functions -uint256 PRF_addr_a_pk(const uint252& a_sk); -uint256 PRF_addr_sk_enc(const uint252& a_sk); -uint256 PRF_nf(const uint252& a_sk, const uint256& rho); -uint256 PRF_pk(const uint252& a_sk, size_t i0, const uint256& h_sig); -uint256 PRF_rho(const uint252& phi, size_t i0, const uint256& h_sig); - //! Sapling functions uint256 PRF_ask(const uint256& sk); uint256 PRF_nsk(const uint256& sk); diff --git a/src/zcash/zip32.h b/src/zcash/zip32.h index 44bc58598..1521dddd1 100644 --- a/src/zcash/zip32.h +++ b/src/zcash/zip32.h @@ -1,4 +1,5 @@ // Copyright (c) 2018 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -134,7 +135,7 @@ struct SaplingExtendedSpendingKey { } }; -typedef boost::variant SpendingKey; +typedef boost::variant SpendingKey; }