desprout
This commit is contained in:
@@ -347,8 +347,6 @@ endif
|
||||
libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
libbitcoin_wallet_a_SOURCES = \
|
||||
utiltest.cpp \
|
||||
utiltest.h \
|
||||
zcbenchmarks.cpp \
|
||||
zcbenchmarks.h \
|
||||
wallet/asyncrpcoperation_mergetoaddress.cpp \
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
#include "zcash/Note.hpp"
|
||||
#include "zcash/Address.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
extern ZCJoinSplit* params;
|
||||
extern int GenZero(int n);
|
||||
extern int GenMax(int n);
|
||||
|
||||
TEST(Transaction, JSDescriptionRandomized) {
|
||||
// construct a merkle tree
|
||||
SproutMerkleTree merkleTree;
|
||||
|
||||
libzcash::SproutSpendingKey k = libzcash::SproutSpendingKey::random();
|
||||
libzcash::SproutPaymentAddress addr = k.address();
|
||||
|
||||
libzcash::SproutNote note(addr.a_pk, 100, uint256(), uint256());
|
||||
|
||||
// commitment from coin
|
||||
uint256 commitment = note.cm();
|
||||
|
||||
// insert commitment into the merkle tree
|
||||
merkleTree.append(commitment);
|
||||
|
||||
// compute the merkle root we will be working with
|
||||
uint256 rt = merkleTree.root();
|
||||
|
||||
auto witness = merkleTree.witness();
|
||||
|
||||
// create JSDescription
|
||||
uint256 joinSplitPubKey;
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs = {
|
||||
libzcash::JSInput(witness, note, k),
|
||||
libzcash::JSInput() // dummy input of zero value
|
||||
};
|
||||
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs = {
|
||||
libzcash::JSOutput(addr, 50),
|
||||
libzcash::JSOutput(addr, 50)
|
||||
};
|
||||
std::array<size_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
std::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
|
||||
{
|
||||
auto jsdesc = JSDescription::Randomized(
|
||||
false,
|
||||
*params, joinSplitPubKey, rt,
|
||||
inputs, outputs,
|
||||
inputMap, outputMap,
|
||||
0, 0, false);
|
||||
|
||||
std::set<size_t> inputSet(inputMap.begin(), inputMap.end());
|
||||
std::set<size_t> expectedInputSet {0, 1};
|
||||
EXPECT_EQ(expectedInputSet, inputSet);
|
||||
|
||||
std::set<size_t> outputSet(outputMap.begin(), outputMap.end());
|
||||
std::set<size_t> expectedOutputSet {0, 1};
|
||||
EXPECT_EQ(expectedOutputSet, outputSet);
|
||||
}
|
||||
|
||||
{
|
||||
auto jsdesc = JSDescription::Randomized(
|
||||
false,
|
||||
*params, joinSplitPubKey, rt,
|
||||
inputs, outputs,
|
||||
inputMap, outputMap,
|
||||
0, 0, false, nullptr, GenZero);
|
||||
|
||||
std::array<size_t, ZC_NUM_JS_INPUTS> expectedInputMap {1, 0};
|
||||
std::array<size_t, ZC_NUM_JS_OUTPUTS> expectedOutputMap {1, 0};
|
||||
EXPECT_EQ(expectedInputMap, inputMap);
|
||||
EXPECT_EQ(expectedOutputMap, outputMap);
|
||||
}
|
||||
|
||||
{
|
||||
auto jsdesc = JSDescription::Randomized(
|
||||
false,
|
||||
*params, joinSplitPubKey, rt,
|
||||
inputs, outputs,
|
||||
inputMap, outputMap,
|
||||
0, 0, false, nullptr, GenMax);
|
||||
|
||||
std::array<size_t, ZC_NUM_JS_INPUTS> expectedInputMap {0, 1};
|
||||
std::array<size_t, ZC_NUM_JS_OUTPUTS> expectedOutputMap {0, 1};
|
||||
EXPECT_EQ(expectedInputMap, inputMap);
|
||||
EXPECT_EQ(expectedOutputMap, outputMap);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
// Copyright (c) 2016-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.
|
||||
|
||||
@@ -84,15 +85,6 @@ private:
|
||||
public:
|
||||
PaymentAddressEncoder(const CChainParams& params) : m_params(params) {}
|
||||
|
||||
std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << zaddr;
|
||||
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
|
||||
data.insert(data.end(), ss.begin(), ss.end());
|
||||
return EncodeBase58Check(data);
|
||||
}
|
||||
|
||||
std::string operator()(const libzcash::SaplingPaymentAddress& zaddr) const
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
@@ -117,17 +109,6 @@ private:
|
||||
public:
|
||||
ViewingKeyEncoder(const CChainParams& params) : m_params(params) {}
|
||||
|
||||
std::string operator()(const libzcash::SproutViewingKey& vk) const
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << vk;
|
||||
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCVIEWING_KEY);
|
||||
data.insert(data.end(), ss.begin(), ss.end());
|
||||
std::string ret = EncodeBase58Check(data);
|
||||
memory_cleanse(data.data(), data.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string operator()(const libzcash::SaplingIncomingViewingKey& vk) const
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
@@ -152,17 +133,6 @@ private:
|
||||
public:
|
||||
SpendingKeyEncoder(const CChainParams& params) : m_params(params) {}
|
||||
|
||||
std::string operator()(const libzcash::SproutSpendingKey& zkey) const
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << zkey;
|
||||
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCSPENDING_KEY);
|
||||
data.insert(data.end(), ss.begin(), ss.end());
|
||||
std::string ret = EncodeBase58Check(data);
|
||||
memory_cleanse(data.data(), data.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string operator()(const libzcash::SaplingExtendedSpendingKey& zkey) const
|
||||
{
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
@@ -324,18 +294,6 @@ std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
|
||||
libzcash::PaymentAddress DecodePaymentAddress(const std::string& str)
|
||||
{
|
||||
std::vector<unsigned char> data;
|
||||
if (DecodeBase58Check(str, data)) {
|
||||
const std::vector<unsigned char>& zaddr_prefix = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
|
||||
if ((data.size() == libzcash::SerializedSproutPaymentAddressSize + zaddr_prefix.size()) &&
|
||||
std::equal(zaddr_prefix.begin(), zaddr_prefix.end(), data.begin())) {
|
||||
CSerializeData serialized(data.begin() + zaddr_prefix.size(), data.end());
|
||||
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
|
||||
libzcash::SproutPaymentAddress ret;
|
||||
ss >> ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
data.clear();
|
||||
auto bech = bech32::Decode(str);
|
||||
if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) &&
|
||||
bech.second.size() == ConvertedSaplingPaymentAddressSize) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core 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.
|
||||
|
||||
@@ -128,15 +129,6 @@ bool CBasicKeyStore::HaveWatchOnly() const
|
||||
return (!setWatchOnly.empty());
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk)
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
auto address = sk.address();
|
||||
mapSproutSpendingKeys[address] = sk;
|
||||
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(sk.receiving_key())));
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Sapling
|
||||
bool CBasicKeyStore::AddSaplingSpendingKey(
|
||||
const libzcash::SaplingExtendedSpendingKey &sk,
|
||||
@@ -155,14 +147,6 @@ bool CBasicKeyStore::AddSaplingSpendingKey(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::AddSproutViewingKey(const libzcash::SproutViewingKey &vk)
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
auto address = vk.address();
|
||||
mapSproutViewingKeys[address] = vk;
|
||||
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(vk.sk_enc)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::AddSaplingFullViewingKey(
|
||||
const libzcash::SaplingFullViewingKey &fvk,
|
||||
@@ -190,18 +174,7 @@ bool CBasicKeyStore::AddSaplingIncomingViewingKey(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk)
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
mapSproutViewingKeys.erase(vk.address());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::HaveSproutViewingKey(const libzcash::SproutPaymentAddress &address) const
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
return mapSproutViewingKeys.count(address) > 0;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::HaveSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk) const
|
||||
{
|
||||
@@ -215,19 +188,6 @@ bool CBasicKeyStore::HaveSaplingIncomingViewingKey(const libzcash::SaplingPaymen
|
||||
return mapSaplingIncomingViewingKeys.count(addr) > 0;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::GetSproutViewingKey(
|
||||
const libzcash::SproutPaymentAddress &address,
|
||||
libzcash::SproutViewingKey &vkOut) const
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
SproutViewingKeyMap::const_iterator mi = mapSproutViewingKeys.find(address);
|
||||
if (mi != mapSproutViewingKeys.end()) {
|
||||
vkOut = mi->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::GetSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk,
|
||||
libzcash::SaplingFullViewingKey &fvkOut) const
|
||||
{
|
||||
|
||||
@@ -120,12 +120,7 @@ protected:
|
||||
KeyMap mapKeys;
|
||||
ScriptMap mapScripts;
|
||||
WatchOnlySet setWatchOnly;
|
||||
/*
|
||||
SproutSpendingKeyMap mapSproutSpendingKeys;
|
||||
SproutViewingKeyMap mapSproutViewingKeys;
|
||||
NoteDecryptorMap mapNoteDecryptors;
|
||||
*/
|
||||
|
||||
|
||||
SaplingSpendingKeyMap mapSaplingSpendingKeys;
|
||||
SaplingFullViewingKeyMap mapSaplingFullViewingKeys;
|
||||
SaplingIncomingViewingKeyMap mapSaplingIncomingViewingKeys;
|
||||
@@ -246,7 +241,6 @@ public:
|
||||
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||
typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
|
||||
//typedef std::map<libzcash::SproutPaymentAddress, std::vector<unsigned char> > CryptedSproutSpendingKeyMap;
|
||||
|
||||
//! Sapling
|
||||
typedef std::map<libzcash::SaplingExtendedFullViewingKey, std::vector<unsigned char> > CryptedSaplingSpendingKeyMap;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2017 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.
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
" \"version\": xxxxx, (numeric) the server version\n"
|
||||
" \"protocolversion\": xxxxx, (numeric) the protocol version\n"
|
||||
" \"walletversion\": xxxxx, (numeric) the wallet version\n"
|
||||
" \"balance\": xxxxxxx, (numeric) the total Komodo balance of the wallet\n"
|
||||
" \"balance\": xxxxxxx, (numeric) the total Hush balance of the wallet\n"
|
||||
" \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
|
||||
" \"timeoffset\": xxxxx, (numeric) the time offset\n"
|
||||
" \"connections\": xxxxx, (numeric) the number of connections\n"
|
||||
@@ -590,30 +590,6 @@ UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk
|
||||
}
|
||||
|
||||
|
||||
class DescribePaymentAddressVisitor : public boost::static_visitor<UniValue>
|
||||
{
|
||||
public:
|
||||
UniValue operator()(const libzcash::InvalidEncoding &zaddr) const { return UniValue(UniValue::VOBJ); }
|
||||
|
||||
UniValue operator()(const libzcash::SaplingPaymentAddress &zaddr) const {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("type", "sapling"));
|
||||
obj.push_back(Pair("diversifier", HexStr(zaddr.d)));
|
||||
obj.push_back(Pair("diversifiedtransmissionkey", zaddr.pk_d.GetHex()));
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain) {
|
||||
libzcash::SaplingIncomingViewingKey ivk;
|
||||
libzcash::SaplingFullViewingKey fvk;
|
||||
bool isMine = pwalletMain->GetSaplingIncomingViewingKey(zaddr, ivk) &&
|
||||
pwalletMain->GetSaplingFullViewingKey(ivk, fvk) &&
|
||||
pwalletMain->HaveSaplingSpendingKey(fvk);
|
||||
obj.push_back(Pair("ismine", isMine));
|
||||
}
|
||||
#endif
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
@@ -650,11 +626,25 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& my
|
||||
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
ret.push_back(Pair("isvalid", isValid));
|
||||
if (isValid)
|
||||
auto zaddr = boost::get<libzcash::SaplingPaymentAddress>(&address);
|
||||
if (isValid && (zaddr != nullptr))
|
||||
{
|
||||
ret.push_back(Pair("address", strAddress));
|
||||
UniValue detail = boost::apply_visitor(DescribePaymentAddressVisitor(), address);
|
||||
ret.pushKVs(detail);
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("type", "sapling"));
|
||||
obj.push_back(Pair("diversifier", HexStr(zaddr->d)));
|
||||
obj.push_back(Pair("diversifiedtransmissionkey", zaddr->pk_d.GetHex()));
|
||||
#ifdef ENABLE_WALLET
|
||||
if (pwalletMain) {
|
||||
libzcash::SaplingIncomingViewingKey ivk;
|
||||
libzcash::SaplingFullViewingKey fvk;
|
||||
bool isMine = pwalletMain->GetSaplingIncomingViewingKey(*zaddr, ivk) &&
|
||||
pwalletMain->GetSaplingFullViewingKey(ivk, fvk) &&
|
||||
pwalletMain->HaveSaplingSpendingKey(fvk);
|
||||
obj.push_back(Pair("ismine", isMine));
|
||||
}
|
||||
#endif
|
||||
ret.pushKVs(obj);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -733,9 +723,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
|
||||
"\nArguments:\n"
|
||||
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
|
||||
"2. \"keys\" (string, required) A json array of keys which are Komodo addresses or hex-encoded public keys\n"
|
||||
"2. \"keys\" (string, required) A json array of keys which are Hush addresses or hex-encoded public keys\n"
|
||||
" [\n"
|
||||
" \"key\" (string) Komodo address or hex-encoded public key\n"
|
||||
" \"key\" (string) Hush address or hex-encoded public key\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
|
||||
@@ -769,10 +759,10 @@ UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||
{
|
||||
if (fHelp || params.size() != 3)
|
||||
throw runtime_error(
|
||||
"verifymessage \"komodoaddress\" \"signature\" \"message\"\n"
|
||||
"verifymessage \"hushaddress\" \"signature\" \"message\"\n"
|
||||
"\nVerify a signed message\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"komodoaddress\" (string, required) The Komodo address to use for the signature.\n"
|
||||
"1. \"hushaddress\" (string, required) The Hush address to use for the signature.\n"
|
||||
"2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
|
||||
"3. \"message\" (string, required) The message that was signed.\n"
|
||||
"\nResult:\n"
|
||||
|
||||
@@ -571,9 +571,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
|
||||
// Verify number of addresses stored in wallet is n1+n2
|
||||
int numAddrs = myaddrs.size();
|
||||
BOOST_CHECK(numAddrs == (2 * n1) + n2);
|
||||
pwalletMain->GetSproutPaymentAddresses(addrs);
|
||||
pwalletMain->GetSaplingPaymentAddresses(saplingAddrs);
|
||||
BOOST_CHECK(addrs.size() + saplingAddrs.size() == numAddrs);
|
||||
BOOST_CHECK(saplingAddrs.size() == numAddrs);
|
||||
|
||||
// Ask wallet to list addresses
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
|
||||
@@ -595,9 +594,6 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
|
||||
std::string newaddress = retValue.get_str();
|
||||
auto address = DecodePaymentAddress(newaddress);
|
||||
BOOST_CHECK(IsValidPaymentAddress(address));
|
||||
BOOST_ASSERT(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
|
||||
auto newAddr = boost::get<libzcash::SproutPaymentAddress>(address);
|
||||
BOOST_CHECK(pwalletMain->HaveSproutSpendingKey(newAddr));
|
||||
|
||||
// Check if too many args
|
||||
BOOST_CHECK_THROW(CallRPC("z_getnewaddress toomanyargs"), runtime_error);
|
||||
|
||||
154
src/utiltest.cpp
154
src/utiltest.cpp
@@ -1,154 +0,0 @@
|
||||
// Copyright (c) 2016 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.
|
||||
|
||||
#include "utiltest.h"
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
CWalletTx GetValidReceive(ZCJoinSplit& params,
|
||||
const libzcash::SproutSpendingKey& sk, CAmount value,
|
||||
bool randomInputs,
|
||||
int32_t version /* = 2 */) {
|
||||
CMutableTransaction mtx;
|
||||
mtx.nVersion = version;
|
||||
mtx.vin.resize(2);
|
||||
if (randomInputs) {
|
||||
mtx.vin[0].prevout.hash = GetRandHash();
|
||||
mtx.vin[1].prevout.hash = GetRandHash();
|
||||
} else {
|
||||
mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
|
||||
mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002");
|
||||
}
|
||||
mtx.vin[0].prevout.n = 0;
|
||||
mtx.vin[1].prevout.n = 0;
|
||||
|
||||
// Generate an ephemeral keypair.
|
||||
uint256 joinSplitPubKey;
|
||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
||||
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
||||
mtx.joinSplitPubKey = joinSplitPubKey;
|
||||
|
||||
std::array<libzcash::JSInput, 2> inputs = {
|
||||
libzcash::JSInput(), // dummy input
|
||||
libzcash::JSInput() // dummy input
|
||||
};
|
||||
|
||||
std::array<libzcash::JSOutput, 2> outputs = {
|
||||
libzcash::JSOutput(sk.address(), value),
|
||||
libzcash::JSOutput(sk.address(), value)
|
||||
};
|
||||
|
||||
// Prepare JoinSplits
|
||||
uint256 rt;
|
||||
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
|
||||
inputs, outputs, 2*value, 0, false};
|
||||
mtx.vjoinsplit.push_back(jsdesc);
|
||||
|
||||
if (version >= 4) {
|
||||
// Shielded Output
|
||||
OutputDescription od;
|
||||
mtx.vShieldedOutput.push_back(od);
|
||||
}
|
||||
|
||||
// Empty output script.
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
// Add the signature
|
||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
||||
dataToBeSigned.begin(), 32,
|
||||
joinSplitPrivKey
|
||||
) == 0);
|
||||
|
||||
CTransaction tx {mtx};
|
||||
CWalletTx wtx {NULL, tx};
|
||||
return wtx;
|
||||
}
|
||||
|
||||
libzcash::SproutNote GetNote(ZCJoinSplit& params,
|
||||
const libzcash::SproutSpendingKey& sk,
|
||||
const CTransaction& tx, size_t js, size_t n) {
|
||||
ZCNoteDecryption decryptor {sk.receiving_key()};
|
||||
auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey);
|
||||
auto note_pt = libzcash::SproutNotePlaintext::decrypt(
|
||||
decryptor,
|
||||
tx.vjoinsplit[js].ciphertexts[n],
|
||||
tx.vjoinsplit[js].ephemeralKey,
|
||||
hSig,
|
||||
(unsigned char) n);
|
||||
return note_pt.note(sk.address());
|
||||
}
|
||||
|
||||
CWalletTx GetValidSpend(ZCJoinSplit& params,
|
||||
const libzcash::SproutSpendingKey& sk,
|
||||
const libzcash::SproutNote& note, CAmount value) {
|
||||
CMutableTransaction mtx;
|
||||
mtx.vout.resize(2);
|
||||
mtx.vout[0].nValue = value;
|
||||
mtx.vout[1].nValue = 0;
|
||||
|
||||
// Generate an ephemeral keypair.
|
||||
uint256 joinSplitPubKey;
|
||||
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
||||
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
||||
mtx.joinSplitPubKey = joinSplitPubKey;
|
||||
|
||||
// Fake tree for the unused witness
|
||||
SproutMerkleTree tree;
|
||||
|
||||
libzcash::JSOutput dummyout;
|
||||
libzcash::JSInput dummyin;
|
||||
|
||||
{
|
||||
if (note.value() > value) {
|
||||
libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random();
|
||||
libzcash::SproutPaymentAddress dummyaddr = dummykey.address();
|
||||
dummyout = libzcash::JSOutput(dummyaddr, note.value() - value);
|
||||
} else if (note.value() < value) {
|
||||
libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random();
|
||||
libzcash::SproutPaymentAddress dummyaddr = dummykey.address();
|
||||
libzcash::SproutNote dummynote(dummyaddr.a_pk, (value - note.value()), uint256(), uint256());
|
||||
tree.append(dummynote.cm());
|
||||
dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey);
|
||||
}
|
||||
}
|
||||
|
||||
tree.append(note.cm());
|
||||
|
||||
std::array<libzcash::JSInput, 2> inputs = {
|
||||
libzcash::JSInput(tree.witness(), note, sk),
|
||||
dummyin
|
||||
};
|
||||
|
||||
std::array<libzcash::JSOutput, 2> outputs = {
|
||||
dummyout, // dummy output
|
||||
libzcash::JSOutput() // dummy output
|
||||
};
|
||||
|
||||
// Prepare JoinSplits
|
||||
uint256 rt = tree.root();
|
||||
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
|
||||
inputs, outputs, 0, value, false};
|
||||
mtx.vjoinsplit.push_back(jsdesc);
|
||||
|
||||
// Empty output script.
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
// Add the signature
|
||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
||||
dataToBeSigned.begin(), 32,
|
||||
joinSplitPrivKey
|
||||
) == 0);
|
||||
CTransaction tx {mtx};
|
||||
CWalletTx wtx {NULL, tx};
|
||||
return wtx;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) 2016 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "wallet/wallet.h"
|
||||
#include "zcash/JoinSplit.hpp"
|
||||
#include "zcash/Note.hpp"
|
||||
#include "zcash/NoteEncryption.hpp"
|
||||
|
||||
CWalletTx GetValidReceive(ZCJoinSplit& params,
|
||||
const libzcash::SproutSpendingKey& sk, CAmount value,
|
||||
bool randomInputs,
|
||||
int32_t version = 2);
|
||||
libzcash::SproutNote GetNote(ZCJoinSplit& params,
|
||||
const libzcash::SproutSpendingKey& sk,
|
||||
const CTransaction& tx, size_t js, size_t n);
|
||||
CWalletTx GetValidSpend(ZCJoinSplit& params,
|
||||
const libzcash::SproutSpendingKey& sk,
|
||||
const libzcash::SproutNote& note, CAmount value);
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2017 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.
|
||||
|
||||
@@ -123,7 +124,6 @@ public:
|
||||
ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount) :
|
||||
m_op(op), sendAmount(sendAmount) {}
|
||||
|
||||
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2009-2013 The Bitcoin Core 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.
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
@@ -168,22 +169,6 @@ static bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsi
|
||||
return key.VerifyPubKey(vchPubKey);
|
||||
}
|
||||
|
||||
static bool DecryptSproutSpendingKey(const CKeyingMaterial& vMasterKey,
|
||||
const std::vector<unsigned char>& vchCryptedSecret,
|
||||
const libzcash::SproutPaymentAddress& address,
|
||||
libzcash::SproutSpendingKey& sk)
|
||||
{
|
||||
CKeyingMaterial vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, address.GetHash(), vchSecret))
|
||||
return false;
|
||||
|
||||
if (vchSecret.size() != libzcash::SerializedSproutSpendingKeySize)
|
||||
return false;
|
||||
|
||||
CSecureDataStream ss(vchSecret, SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss >> sk;
|
||||
return sk.address() == address;
|
||||
}
|
||||
|
||||
static bool DecryptSaplingSpendingKey(const CKeyingMaterial& vMasterKey,
|
||||
const std::vector<unsigned char>& vchCryptedSecret,
|
||||
@@ -207,7 +192,7 @@ bool CCryptoKeyStore::SetCrypted()
|
||||
LOCK2(cs_KeyStore, cs_SpendingKeyStore);
|
||||
if (fUseCrypto)
|
||||
return true;
|
||||
if (!(mapKeys.empty() && mapSproutSpendingKeys.empty() && mapSaplingSpendingKeys.empty()))
|
||||
if (!(mapKeys.empty() && mapSaplingSpendingKeys.empty()))
|
||||
return false;
|
||||
fUseCrypto = true;
|
||||
return true;
|
||||
@@ -260,21 +245,6 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
if (fDecryptionThoroughlyChecked)
|
||||
break;
|
||||
}
|
||||
CryptedSproutSpendingKeyMap::const_iterator miSprout = mapCryptedSproutSpendingKeys.begin();
|
||||
for (; miSprout != mapCryptedSproutSpendingKeys.end(); ++miSprout)
|
||||
{
|
||||
const libzcash::SproutPaymentAddress &address = (*miSprout).first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*miSprout).second;
|
||||
libzcash::SproutSpendingKey sk;
|
||||
if (!DecryptSproutSpendingKey(vMasterKeyIn, vchCryptedSecret, address, sk))
|
||||
{
|
||||
keyFail = true;
|
||||
break;
|
||||
}
|
||||
keyPass = true;
|
||||
if (fDecryptionThoroughlyChecked)
|
||||
break;
|
||||
}
|
||||
CryptedSaplingSpendingKeyMap::const_iterator miSapling = mapCryptedSaplingSpendingKeys.begin();
|
||||
for (; miSapling != mapCryptedSaplingSpendingKeys.end(); ++miSapling)
|
||||
{
|
||||
@@ -292,7 +262,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
}
|
||||
if (keyPass && keyFail)
|
||||
{
|
||||
LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
|
||||
LogPrintf("Oh shit! The wallet is probably corrupted: Some keys decrypt but not all.\n");
|
||||
assert(false);
|
||||
}
|
||||
if (keyFail || !keyPass)
|
||||
@@ -440,30 +410,6 @@ bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) co
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk)
|
||||
{
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::AddSproutSpendingKey(sk);
|
||||
|
||||
if (IsLocked())
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << sk;
|
||||
CKeyingMaterial vchSecret(ss.begin(), ss.end());
|
||||
auto address = sk.address();
|
||||
if (!EncryptSecret(vMasterKey, vchSecret, address.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
if (!AddCryptedSproutSpendingKey(address, sk.receiving_key(), vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddSaplingSpendingKey(
|
||||
const libzcash::SaplingExtendedSpendingKey &sk,
|
||||
const libzcash::SaplingPaymentAddress &defaultAddr)
|
||||
@@ -494,22 +440,6 @@ bool CCryptoKeyStore::AddSaplingSpendingKey(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedSproutSpendingKey(
|
||||
const libzcash::SproutPaymentAddress &address,
|
||||
const libzcash::ReceivingKey &rk,
|
||||
const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
mapCryptedSproutSpendingKeys[address] = vchCryptedSecret;
|
||||
mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(rk)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedSaplingSpendingKey(
|
||||
const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||
const std::vector<unsigned char> &vchCryptedSecret,
|
||||
@@ -531,23 +461,6 @@ bool CCryptoKeyStore::AddCryptedSaplingSpendingKey(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetSproutSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_SpendingKeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::GetSproutSpendingKey(address, skOut);
|
||||
|
||||
CryptedSproutSpendingKeyMap::const_iterator mi = mapCryptedSproutSpendingKeys.find(address);
|
||||
if (mi != mapCryptedSproutSpendingKeys.end())
|
||||
{
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second;
|
||||
return DecryptSproutSpendingKey(vMasterKey, vchCryptedSecret, address, skOut);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, libzcash::SaplingExtendedSpendingKey &skOut) const
|
||||
{
|
||||
{
|
||||
@@ -603,22 +516,6 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
}
|
||||
}
|
||||
mapKeys.clear();
|
||||
BOOST_FOREACH(SproutSpendingKeyMap::value_type& mSproutSpendingKey, mapSproutSpendingKeys)
|
||||
{
|
||||
const libzcash::SproutSpendingKey &sk = mSproutSpendingKey.second;
|
||||
CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << sk;
|
||||
CKeyingMaterial vchSecret(ss.begin(), ss.end());
|
||||
libzcash::SproutPaymentAddress address = sk.address();
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, vchSecret, address.GetHash(), vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
if (!AddCryptedSproutSpendingKey(address, sk.receiving_key(), vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
mapSproutSpendingKeys.clear();
|
||||
//! Sapling key support
|
||||
BOOST_FOREACH(SaplingSpendingKeyMap::value_type& mSaplingSpendingKey, mapSaplingSpendingKeys)
|
||||
{
|
||||
|
||||
@@ -139,341 +139,8 @@ TEST(WalletTests, SetupDatadirLocationRunAsFirstTest) {
|
||||
boost::filesystem::create_directories(pathTemp);
|
||||
mapArgs["-datadir"] = pathTemp.string();
|
||||
}
|
||||
/*
|
||||
|
||||
TEST(WalletTests, SproutNoteDataSerialisation) {
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
mapSproutNoteData_t noteData;
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
SproutMerkleTree tree;
|
||||
nd.witnesses.push_front(tree.witness());
|
||||
noteData[jsoutpt] = nd;
|
||||
|
||||
CDataStream ss(SER_DISK, CLIENT_VERSION);
|
||||
ss << noteData;
|
||||
|
||||
mapSproutNoteData_t noteData2;
|
||||
ss >> noteData2;
|
||||
|
||||
EXPECT_EQ(noteData, noteData2);
|
||||
EXPECT_EQ(noteData[jsoutpt].witnesses, noteData2[jsoutpt].witnesses);
|
||||
}
|
||||
|
||||
|
||||
TEST(WalletTests, FindUnspentSproutNotes) {
|
||||
SelectParams(CBaseChainParams::TESTNET);
|
||||
CWallet wallet;
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
mapSproutNoteData_t noteData;
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
noteData[jsoutpt] = nd;
|
||||
|
||||
wtx.SetSproutNoteData(noteData);
|
||||
wallet.AddToWallet(wtx, true, NULL);
|
||||
EXPECT_FALSE(wallet.IsSproutSpent(nullifier));
|
||||
|
||||
// We currently have an unspent and unconfirmed note in the wallet (depth of -1)
|
||||
std::vector<CSproutNotePlaintextEntry> sproutEntries;
|
||||
std::vector<SaplingNoteEntry> saplingEntries;
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0);
|
||||
EXPECT_EQ(0, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", -1);
|
||||
EXPECT_EQ(1, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
|
||||
// Fake-mine the transaction
|
||||
EXPECT_EQ(-1, chainActive.Height());
|
||||
CBlock block;
|
||||
block.vtx.push_back(wtx);
|
||||
block.hashMerkleRoot = block.BuildMerkleTree();
|
||||
auto blockHash = block.GetHash();
|
||||
CBlockIndex fakeIndex {block};
|
||||
mapBlockIndex.insert(std::make_pair(blockHash, &fakeIndex));
|
||||
chainActive.SetTip(&fakeIndex);
|
||||
EXPECT_TRUE(chainActive.Contains(&fakeIndex));
|
||||
EXPECT_EQ(0, chainActive.Height());
|
||||
|
||||
wtx.SetMerkleBranch(block);
|
||||
wallet.AddToWallet(wtx, true, NULL);
|
||||
EXPECT_FALSE(wallet.IsSproutSpent(nullifier));
|
||||
|
||||
|
||||
// We now have an unspent and confirmed note in the wallet (depth of 1)
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0);
|
||||
EXPECT_EQ(1, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 1);
|
||||
EXPECT_EQ(1, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2);
|
||||
EXPECT_EQ(0, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
|
||||
|
||||
// Let's spend the note.
|
||||
auto wtx2 = GetValidSpend(sk, note, 5);
|
||||
wallet.AddToWallet(wtx2, true, NULL);
|
||||
EXPECT_FALSE(wallet.IsSproutSpent(nullifier));
|
||||
|
||||
// Fake-mine a spend transaction
|
||||
EXPECT_EQ(0, chainActive.Height());
|
||||
CBlock block2;
|
||||
block2.vtx.push_back(wtx2);
|
||||
block2.hashMerkleRoot = block2.BuildMerkleTree();
|
||||
block2.hashPrevBlock = blockHash;
|
||||
auto blockHash2 = block2.GetHash();
|
||||
CBlockIndex fakeIndex2 {block2};
|
||||
mapBlockIndex.insert(std::make_pair(blockHash2, &fakeIndex2));
|
||||
fakeIndex2.SetHeight(1);
|
||||
chainActive.SetTip(&fakeIndex2);
|
||||
EXPECT_TRUE(chainActive.Contains(&fakeIndex2));
|
||||
EXPECT_EQ(1, chainActive.Height());
|
||||
|
||||
wtx2.SetMerkleBranch(block2);
|
||||
wallet.AddToWallet(wtx2, true, NULL);
|
||||
EXPECT_TRUE(wallet.IsSproutSpent(nullifier));
|
||||
|
||||
// The note has been spent. By default, GetFilteredNotes() ignores spent notes.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0);
|
||||
EXPECT_EQ(0, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
// Let's include spent notes to retrieve it.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0, false);
|
||||
EXPECT_EQ(1, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
// The spent note has two confirmations.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2, false);
|
||||
EXPECT_EQ(1, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
// It does not have 3 confirmations.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 3, false);
|
||||
EXPECT_EQ(0, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
|
||||
|
||||
// Let's receive a new note
|
||||
CWalletTx wtx3;
|
||||
{
|
||||
auto wtx = GetValidReceive(sk, 20, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
mapSproutNoteData_t noteData;
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
noteData[jsoutpt] = nd;
|
||||
|
||||
wtx.SetSproutNoteData(noteData);
|
||||
wallet.AddToWallet(wtx, true, NULL);
|
||||
EXPECT_FALSE(wallet.IsSproutSpent(nullifier));
|
||||
|
||||
wtx3 = wtx;
|
||||
}
|
||||
|
||||
// Fake-mine the new transaction
|
||||
EXPECT_EQ(1, chainActive.Height());
|
||||
CBlock block3;
|
||||
block3.vtx.push_back(wtx3);
|
||||
block3.hashMerkleRoot = block3.BuildMerkleTree();
|
||||
block3.hashPrevBlock = blockHash2;
|
||||
auto blockHash3 = block3.GetHash();
|
||||
CBlockIndex fakeIndex3 {block3};
|
||||
mapBlockIndex.insert(std::make_pair(blockHash3, &fakeIndex3));
|
||||
fakeIndex3.SetHeight(2);
|
||||
chainActive.SetTip(&fakeIndex3);
|
||||
EXPECT_TRUE(chainActive.Contains(&fakeIndex3));
|
||||
EXPECT_EQ(2, chainActive.Height());
|
||||
|
||||
wtx3.SetMerkleBranch(block3);
|
||||
wallet.AddToWallet(wtx3, true, NULL);
|
||||
|
||||
// We now have an unspent note which has one confirmation, in addition to our spent note.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 1);
|
||||
EXPECT_EQ(1, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
// Let's return the spent note too.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 1, false);
|
||||
EXPECT_EQ(2, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
// Increasing number of confirmations will exclude our new unspent note.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2, false);
|
||||
EXPECT_EQ(1, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
// If we also ignore spent notes at this depth, we won't find any notes.
|
||||
wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2, true);
|
||||
EXPECT_EQ(0, sproutEntries.size());
|
||||
sproutEntries.clear();
|
||||
saplingEntries.clear();
|
||||
|
||||
// Tear down
|
||||
chainActive.SetTip(NULL);
|
||||
mapBlockIndex.erase(blockHash);
|
||||
mapBlockIndex.erase(blockHash2);
|
||||
mapBlockIndex.erase(blockHash3);
|
||||
}
|
||||
|
||||
|
||||
TEST(WalletTests, SetSproutNoteAddrsInCWalletTx) {
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
EXPECT_EQ(0, wtx.mapSproutNoteData.size());
|
||||
|
||||
mapSproutNoteData_t noteData;
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
noteData[jsoutpt] = nd;
|
||||
|
||||
wtx.SetSproutNoteData(noteData);
|
||||
EXPECT_EQ(noteData, wtx.mapSproutNoteData);
|
||||
}
|
||||
|
||||
TEST(WalletTests, SetSaplingNoteAddrsInCWalletTx) {
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
|
||||
auto consensusParams = Params().GetConsensus();
|
||||
|
||||
TestWallet wallet;
|
||||
|
||||
std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
|
||||
HDSeed seed(rawSeed);
|
||||
auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed);
|
||||
auto expsk = sk.expsk;
|
||||
auto fvk = expsk.full_viewing_key();
|
||||
auto ivk = fvk.in_viewing_key();
|
||||
auto pk = sk.DefaultAddress();
|
||||
|
||||
libzcash::SaplingNote note(pk, 50000);
|
||||
auto cm = note.cm().get();
|
||||
SaplingMerkleTree tree;
|
||||
tree.append(cm);
|
||||
auto anchor = tree.root();
|
||||
auto witness = tree.witness();
|
||||
|
||||
auto nf = note.nullifier(fvk, witness.position());
|
||||
ASSERT_TRUE(nf);
|
||||
uint256 nullifier = nf.get();
|
||||
|
||||
auto builder = TransactionBuilder(consensusParams, 1);
|
||||
ASSERT_TRUE(builder.AddSaplingSpend(expsk, note, anchor, witness));
|
||||
builder.AddSaplingOutput(fvk.ovk, pk, 50000, {});
|
||||
builder.SetFee(0);
|
||||
auto maybe_tx = builder.Build();
|
||||
ASSERT_EQ(static_cast<bool>(maybe_tx), true);
|
||||
auto tx = maybe_tx.get();
|
||||
|
||||
CWalletTx wtx {&wallet, tx};
|
||||
|
||||
EXPECT_EQ(0, wtx.mapSaplingNoteData.size());
|
||||
mapSaplingNoteData_t noteData;
|
||||
|
||||
SaplingOutPoint op {wtx.GetHash(), 0};
|
||||
SaplingNoteData nd;
|
||||
nd.nullifier = nullifier;
|
||||
nd.ivk = ivk;
|
||||
nd.witnesses.push_front(witness);
|
||||
nd.witnessHeight = 123;
|
||||
noteData.insert(std::make_pair(op, nd));
|
||||
|
||||
wtx.SetSaplingNoteData(noteData);
|
||||
EXPECT_EQ(noteData, wtx.mapSaplingNoteData);
|
||||
|
||||
// Test individual fields in case equality operator is defined/changed.
|
||||
EXPECT_EQ(ivk, wtx.mapSaplingNoteData[op].ivk);
|
||||
EXPECT_EQ(nullifier, wtx.mapSaplingNoteData[op].nullifier);
|
||||
EXPECT_EQ(nd.witnessHeight, wtx.mapSaplingNoteData[op].witnessHeight);
|
||||
EXPECT_TRUE(witness == wtx.mapSaplingNoteData[op].witnesses.front());
|
||||
|
||||
// Revert to default
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
|
||||
}
|
||||
|
||||
TEST(WalletTests, SetSproutInvalidNoteAddrsInCWalletTx) {
|
||||
CWalletTx wtx;
|
||||
EXPECT_EQ(0, wtx.mapSproutNoteData.size());
|
||||
|
||||
mapSproutNoteData_t noteData;
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address(), uint256()};
|
||||
noteData[jsoutpt] = nd;
|
||||
|
||||
EXPECT_THROW(wtx.SetSproutNoteData(noteData), std::logic_error);
|
||||
}
|
||||
|
||||
// The following test is the same as SetInvalidSaplingNoteDataInCWalletTx
|
||||
// TEST(WalletTests, SetSaplingInvalidNoteAddrsInCWalletTx)
|
||||
|
||||
// Cannot add note data for an index which does not exist in tx.vShieldedOutput
|
||||
TEST(WalletTests, SetInvalidSaplingNoteDataInCWalletTx) {
|
||||
CWalletTx wtx;
|
||||
EXPECT_EQ(0, wtx.mapSaplingNoteData.size());
|
||||
|
||||
mapSaplingNoteData_t noteData;
|
||||
SaplingOutPoint op {uint256(), 1};
|
||||
SaplingNoteData nd;
|
||||
noteData.insert(std::make_pair(op, nd));
|
||||
|
||||
EXPECT_THROW(wtx.SetSaplingNoteData(noteData), std::logic_error);
|
||||
}
|
||||
|
||||
TEST(WalletTests, GetSproutNoteNullifier) {
|
||||
CWallet wallet;
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
auto address = sk.address();
|
||||
auto dec = ZCNoteDecryption(sk.receiving_key());
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
auto hSig = wtx.vjoinsplit[0].h_sig(
|
||||
*params, wtx.joinSplitPubKey);
|
||||
|
||||
auto ret = wallet.GetSproutNoteNullifier(
|
||||
wtx.vjoinsplit[0],
|
||||
address,
|
||||
dec,
|
||||
hSig, 1);
|
||||
EXPECT_NE(nullifier, ret);
|
||||
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
ret = wallet.GetSproutNoteNullifier(
|
||||
wtx.vjoinsplit[0],
|
||||
address,
|
||||
dec,
|
||||
hSig, 1);
|
||||
EXPECT_EQ(nullifier, ret);
|
||||
}
|
||||
|
||||
TEST(WalletTests, FindMySaplingNotes) {
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
@@ -577,92 +244,6 @@ TEST(WalletTests, FindMySaplingNotesWithIvkOnly) {
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
|
||||
}
|
||||
|
||||
TEST(WalletTests, FindMySproutNotes) {
|
||||
CWallet wallet;
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
auto sk2 = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk2);
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
auto noteMap = wallet.FindMySproutNotes(wtx);
|
||||
EXPECT_EQ(0, noteMap.size());
|
||||
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
noteMap = wallet.FindMySproutNotes(wtx);
|
||||
EXPECT_EQ(2, noteMap.size());
|
||||
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
EXPECT_EQ(1, noteMap.count(jsoutpt));
|
||||
EXPECT_EQ(nd, noteMap[jsoutpt]);
|
||||
}
|
||||
|
||||
TEST(WalletTests, FindMySproutNotesInEncryptedWallet) {
|
||||
TestWallet wallet;
|
||||
uint256 r {GetRandHash()};
|
||||
CKeyingMaterial vMasterKey (r.begin(), r.end());
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
ASSERT_TRUE(wallet.EncryptKeys(vMasterKey));
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
auto noteMap = wallet.FindMySproutNotes(wtx);
|
||||
EXPECT_EQ(2, noteMap.size());
|
||||
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
EXPECT_EQ(1, noteMap.count(jsoutpt));
|
||||
EXPECT_NE(nd, noteMap[jsoutpt]);
|
||||
|
||||
ASSERT_TRUE(wallet.Unlock(vMasterKey));
|
||||
|
||||
noteMap = wallet.FindMySproutNotes(wtx);
|
||||
EXPECT_EQ(2, noteMap.size());
|
||||
EXPECT_EQ(1, noteMap.count(jsoutpt));
|
||||
EXPECT_EQ(nd, noteMap[jsoutpt]);
|
||||
}
|
||||
|
||||
TEST(WalletTests, GetConflictedSproutNotes) {
|
||||
CWallet wallet;
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
auto wtx2 = GetValidSpend(sk, note, 5);
|
||||
auto wtx3 = GetValidSpend(sk, note, 10);
|
||||
auto hash2 = wtx2.GetHash();
|
||||
auto hash3 = wtx3.GetHash();
|
||||
|
||||
// No conflicts for no spends
|
||||
EXPECT_EQ(0, wallet.GetConflicts(hash2).size());
|
||||
wallet.AddToWallet(wtx, true, NULL);
|
||||
EXPECT_EQ(0, wallet.GetConflicts(hash2).size());
|
||||
|
||||
// No conflicts for one spend
|
||||
wallet.AddToWallet(wtx2, true, NULL);
|
||||
EXPECT_EQ(0, wallet.GetConflicts(hash2).size());
|
||||
|
||||
// Conflicts for two spends
|
||||
wallet.AddToWallet(wtx3, true, NULL);
|
||||
auto c3 = wallet.GetConflicts(hash2);
|
||||
EXPECT_EQ(2, c3.size());
|
||||
EXPECT_EQ(std::set<uint256>({hash2, hash3}), c3);
|
||||
}
|
||||
|
||||
// Generate note A and spend to create note B, from which we spend to create two conflicting transactions
|
||||
TEST(WalletTests, GetConflictedSaplingNotes) {
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
@@ -1735,88 +1316,6 @@ TEST(WalletTests, SetBestChainIgnoresTxsWithoutShieldedData) {
|
||||
wallet.SetBestChain(walletdb, loc);
|
||||
}
|
||||
|
||||
TEST(WalletTests, UpdateSproutNullifierNoteMap) {
|
||||
TestWallet wallet;
|
||||
uint256 r {GetRandHash()};
|
||||
CKeyingMaterial vMasterKey (r.begin(), r.end());
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
ASSERT_TRUE(wallet.EncryptKeys(vMasterKey));
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
|
||||
// Pretend that we called FindMySproutNotes while the wallet was locked
|
||||
mapSproutNoteData_t noteData;
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
|
||||
SproutNoteData nd {sk.address()};
|
||||
noteData[jsoutpt] = nd;
|
||||
wtx.SetSproutNoteData(noteData);
|
||||
|
||||
wallet.AddToWallet(wtx, true, NULL);
|
||||
EXPECT_EQ(0, wallet.mapSproutNullifiersToNotes.count(nullifier));
|
||||
|
||||
EXPECT_FALSE(wallet.UpdateNullifierNoteMap());
|
||||
|
||||
ASSERT_TRUE(wallet.Unlock(vMasterKey));
|
||||
|
||||
EXPECT_TRUE(wallet.UpdateNullifierNoteMap());
|
||||
EXPECT_EQ(1, wallet.mapSproutNullifiersToNotes.count(nullifier));
|
||||
EXPECT_EQ(wtx.GetHash(), wallet.mapSproutNullifiersToNotes[nullifier].hash);
|
||||
EXPECT_EQ(0, wallet.mapSproutNullifiersToNotes[nullifier].js);
|
||||
EXPECT_EQ(1, wallet.mapSproutNullifiersToNotes[nullifier].n);
|
||||
}
|
||||
|
||||
TEST(WalletTests, UpdatedSproutNoteData) {
|
||||
TestWallet wallet;
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto note = GetNote(sk, wtx, 0, 0);
|
||||
auto note2 = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
auto nullifier2 = note2.nullifier(sk);
|
||||
auto wtx2 = wtx;
|
||||
|
||||
// First pretend we added the tx to the wallet and
|
||||
// we don't have the key for the second note
|
||||
mapSproutNoteData_t noteData;
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 0};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
noteData[jsoutpt] = nd;
|
||||
wtx.SetSproutNoteData(noteData);
|
||||
|
||||
// Pretend we mined the tx by adding a fake witness
|
||||
SproutMerkleTree tree;
|
||||
wtx.mapSproutNoteData[jsoutpt].witnesses.push_front(tree.witness());
|
||||
wtx.mapSproutNoteData[jsoutpt].witnessHeight = 100;
|
||||
|
||||
// Now pretend we added the key for the second note, and
|
||||
// the tx was "added" to the wallet again to update it.
|
||||
// This happens via the 'z_importkey' RPC method.
|
||||
JSOutPoint jsoutpt2 {wtx2.GetHash(), 0, 1};
|
||||
SproutNoteData nd2 {sk.address(), nullifier2};
|
||||
noteData[jsoutpt2] = nd2;
|
||||
wtx2.SetSproutNoteData(noteData);
|
||||
|
||||
// The txs should initially be different
|
||||
EXPECT_NE(wtx.mapSproutNoteData, wtx2.mapSproutNoteData);
|
||||
EXPECT_EQ(1, wtx.mapSproutNoteData[jsoutpt].witnesses.size());
|
||||
EXPECT_EQ(100, wtx.mapSproutNoteData[jsoutpt].witnessHeight);
|
||||
|
||||
// After updating, they should be the same
|
||||
EXPECT_TRUE(wallet.UpdatedNoteData(wtx2, wtx));
|
||||
EXPECT_EQ(wtx.mapSproutNoteData, wtx2.mapSproutNoteData);
|
||||
EXPECT_EQ(1, wtx.mapSproutNoteData[jsoutpt].witnesses.size());
|
||||
EXPECT_EQ(100, wtx.mapSproutNoteData[jsoutpt].witnessHeight);
|
||||
// TODO: The new note should get witnessed (but maybe not here) (#1350)
|
||||
}
|
||||
|
||||
TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
|
||||
@@ -1941,37 +1440,6 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
|
||||
}
|
||||
|
||||
TEST(WalletTests, MarkAffectedSproutTransactionsDirty) {
|
||||
TestWallet wallet;
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto hash = wtx.GetHash();
|
||||
auto note = GetNote(sk, wtx, 0, 1);
|
||||
auto nullifier = note.nullifier(sk);
|
||||
auto wtx2 = GetValidSpend(sk, note, 5);
|
||||
|
||||
mapSproutNoteData_t noteData;
|
||||
JSOutPoint jsoutpt {hash, 0, 1};
|
||||
SproutNoteData nd {sk.address(), nullifier};
|
||||
noteData[jsoutpt] = nd;
|
||||
|
||||
wtx.SetSproutNoteData(noteData);
|
||||
wallet.AddToWallet(wtx, true, NULL);
|
||||
wallet.MarkAffectedTransactionsDirty(wtx);
|
||||
|
||||
// After getting a cached value, the first tx should be clean
|
||||
wallet.mapWallet[hash].GetDebit(ISMINE_ALL);
|
||||
EXPECT_TRUE(wallet.mapWallet[hash].fDebitCached);
|
||||
|
||||
// After adding the note spend, the first tx should be dirty
|
||||
wallet.AddToWallet(wtx2, true, NULL);
|
||||
wallet.MarkAffectedTransactionsDirty(wtx2);
|
||||
EXPECT_FALSE(wallet.mapWallet[hash].fDebitCached);
|
||||
}
|
||||
|
||||
TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
|
||||
@@ -1999,7 +1467,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
|
||||
auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID());
|
||||
|
||||
// Generate shielding tx from transparent to Sapling
|
||||
// 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee
|
||||
// 0.0005 t-HUSH in, 0.0004 z-HUSH out, 0.0001 t-HUSH fee
|
||||
auto builder = TransactionBuilder(consensusParams, 1, &keystore);
|
||||
builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000);
|
||||
builder.AddSaplingOutput(fvk.ovk, pk, 40000, {});
|
||||
@@ -2093,39 +1561,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
|
||||
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
|
||||
}
|
||||
|
||||
TEST(WalletTests, SproutNoteLocking) {
|
||||
TestWallet wallet;
|
||||
|
||||
auto sk = libzcash::SproutSpendingKey::random();
|
||||
wallet.AddSproutSpendingKey(sk);
|
||||
|
||||
auto wtx = GetValidReceive(sk, 10, true);
|
||||
auto wtx2 = GetValidReceive(sk, 10, true);
|
||||
|
||||
JSOutPoint jsoutpt {wtx.GetHash(), 0, 0};
|
||||
JSOutPoint jsoutpt2 {wtx2.GetHash(),0, 0};
|
||||
|
||||
// Test selective locking
|
||||
wallet.LockNote(jsoutpt);
|
||||
EXPECT_TRUE(wallet.IsLockedNote(jsoutpt));
|
||||
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt2));
|
||||
|
||||
// Test selective unlocking
|
||||
wallet.UnlockNote(jsoutpt);
|
||||
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt));
|
||||
|
||||
// Test multiple locking
|
||||
wallet.LockNote(jsoutpt);
|
||||
wallet.LockNote(jsoutpt2);
|
||||
EXPECT_TRUE(wallet.IsLockedNote(jsoutpt));
|
||||
EXPECT_TRUE(wallet.IsLockedNote(jsoutpt2));
|
||||
|
||||
// Test unlock all
|
||||
wallet.UnlockAllSproutNotes();
|
||||
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt));
|
||||
EXPECT_FALSE(wallet.IsLockedNote(jsoutpt2));
|
||||
}
|
||||
*/
|
||||
|
||||
TEST(WalletTests, SaplingNoteLocking) {
|
||||
TestWallet wallet;
|
||||
|
||||
@@ -5487,34 +5487,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp
|
||||
"Cannot send between Sprout and Sapling addresses using z_mergetoaddress");
|
||||
}
|
||||
|
||||
// Find unspent notes and update estimated size
|
||||
for (const CSproutNotePlaintextEntry& entry : sproutEntries) {
|
||||
noteCounter++;
|
||||
CAmount nValue = entry.plaintext.value();
|
||||
|
||||
if (!maxedOutNotesFlag) {
|
||||
// If we haven't added any notes yet and the merge is to a
|
||||
// z-address, we have already accounted for the first JoinSplit.
|
||||
size_t increase = (sproutNoteInputs.empty() && !isToSproutZaddr) || (sproutNoteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0;
|
||||
if (estimatedTxSize + increase >= max_tx_size ||
|
||||
(sproutNoteLimit > 0 && noteCounter > sproutNoteLimit))
|
||||
{
|
||||
maxedOutNotesFlag = true;
|
||||
} else {
|
||||
estimatedTxSize += increase;
|
||||
auto zaddr = entry.address;
|
||||
SproutSpendingKey zkey;
|
||||
pwalletMain->GetSproutSpendingKey(zaddr, zkey);
|
||||
sproutNoteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey);
|
||||
mergedNoteValue += nValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxedOutNotesFlag) {
|
||||
remainingNoteValue += nValue;
|
||||
}
|
||||
}
|
||||
|
||||
for (const SaplingNoteEntry& entry : saplingEntries) {
|
||||
noteCounter++;
|
||||
CAmount nValue = entry.note.value();
|
||||
|
||||
@@ -1408,7 +1408,6 @@ private:
|
||||
public:
|
||||
PaymentAddressBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {}
|
||||
|
||||
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
@@ -1421,7 +1420,6 @@ private:
|
||||
public:
|
||||
IncomingViewingKeyBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {}
|
||||
|
||||
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
@@ -1433,7 +1431,6 @@ private:
|
||||
public:
|
||||
HaveSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {}
|
||||
|
||||
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
||||
bool operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
@@ -1445,7 +1442,6 @@ private:
|
||||
public:
|
||||
GetSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {}
|
||||
|
||||
boost::optional<libzcash::SpendingKey> operator()(const libzcash::SproutPaymentAddress &zaddr) const;
|
||||
boost::optional<libzcash::SpendingKey> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
||||
boost::optional<libzcash::SpendingKey> operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
@@ -1517,7 +1513,6 @@ public:
|
||||
) : m_wallet(wallet), params(params), nTime(_nTime), hdKeypath(_hdKeypath), seedFpStr(_seedFp), log(_log) {}
|
||||
|
||||
|
||||
SpendingKeyAddResult operator()(const libzcash::SproutSpendingKey &sk) const;
|
||||
SpendingKeyAddResult operator()(const libzcash::SaplingExtendedSpendingKey &sk) const;
|
||||
SpendingKeyAddResult operator()(const libzcash::InvalidEncoding& no) const;
|
||||
};
|
||||
|
||||
@@ -653,6 +653,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
}
|
||||
else if (strType == "czkey")
|
||||
{
|
||||
/*
|
||||
libzcash::SproutPaymentAddress addr;
|
||||
ssKey >> addr;
|
||||
// Deserialization of a pair is just one item after another
|
||||
@@ -663,12 +664,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
ssValue >> vchCryptedSecret;
|
||||
wss.nCKeys++;
|
||||
|
||||
//if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret))
|
||||
//{
|
||||
// strErr = "Error reading wallet database: LoadCryptedZKey failed";
|
||||
// return false;
|
||||
//}
|
||||
//wss.fIsEncrypted = true;
|
||||
if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret))
|
||||
{
|
||||
strErr = "Error reading wallet database: LoadCryptedZKey failed";
|
||||
return false;
|
||||
}
|
||||
wss.fIsEncrypted = true;
|
||||
*/
|
||||
}
|
||||
else if (strType == "csapzkey")
|
||||
{
|
||||
@@ -704,11 +706,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
}
|
||||
else if (strType == "zkeymeta")
|
||||
{
|
||||
/*
|
||||
libzcash::SproutPaymentAddress addr;
|
||||
ssKey >> addr;
|
||||
CKeyMetadata keyMeta;
|
||||
ssValue >> keyMeta;
|
||||
wss.nZKeyMeta++;
|
||||
*/
|
||||
|
||||
// pwallet->LoadZKeyMetadata(addr, keyMeta);
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
||||
// Copyright (c) 2009-2013 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
@@ -199,23 +200,15 @@ public:
|
||||
bool WriteHDChain(const CHDChain& chain);
|
||||
|
||||
/// Write spending key to wallet database, where key is payment address and value is spending key.
|
||||
bool WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta);
|
||||
bool WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk,
|
||||
const libzcash::SaplingExtendedSpendingKey &key,
|
||||
const CKeyMetadata &keyMeta);
|
||||
bool WriteSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr,
|
||||
const libzcash::SaplingIncomingViewingKey &ivk);
|
||||
bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr,
|
||||
const libzcash::ReceivingKey & rk,
|
||||
const std::vector<unsigned char>& vchCryptedSecret,
|
||||
const CKeyMetadata &keyMeta);
|
||||
bool WriteCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk,
|
||||
const std::vector<unsigned char>& vchCryptedSecret,
|
||||
const CKeyMetadata &keyMeta);
|
||||
|
||||
bool WriteSproutViewingKey(const libzcash::SproutViewingKey &vk);
|
||||
bool EraseSproutViewingKey(const libzcash::SproutViewingKey &vk);
|
||||
|
||||
private:
|
||||
CWalletDB(const CWalletDB&);
|
||||
void operator=(const CWalletDB&);
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright (c) 2019-2020 The Hush developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
#include "Address.hpp"
|
||||
#include "NoteEncryption.hpp"
|
||||
#include "hash.h"
|
||||
@@ -13,36 +17,6 @@ const uint32_t SAPLING_BRANCH_ID = 0x76b809bb;
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
uint256 SproutPaymentAddress::GetHash() const {
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << *this;
|
||||
return Hash(ss.begin(), ss.end());
|
||||
}
|
||||
|
||||
uint256 ReceivingKey::pk_enc() const {
|
||||
return ZCNoteEncryption::generate_pubkey(*this);
|
||||
}
|
||||
|
||||
SproutPaymentAddress SproutViewingKey::address() const {
|
||||
return SproutPaymentAddress(a_pk, sk_enc.pk_enc());
|
||||
}
|
||||
|
||||
ReceivingKey SproutSpendingKey::receiving_key() const {
|
||||
return ReceivingKey(ZCNoteEncryption::generate_privkey(*this));
|
||||
}
|
||||
|
||||
SproutViewingKey SproutSpendingKey::viewing_key() const {
|
||||
return SproutViewingKey(PRF_addr_a_pk(*this), receiving_key());
|
||||
}
|
||||
|
||||
SproutSpendingKey SproutSpendingKey::random() {
|
||||
return SproutSpendingKey(random_uint252());
|
||||
}
|
||||
|
||||
SproutPaymentAddress SproutSpendingKey::address() const {
|
||||
return viewing_key().address();
|
||||
}
|
||||
|
||||
//! Sapling
|
||||
uint256 SaplingPaymentAddress::GetHash() const {
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
@@ -119,10 +93,6 @@ class IsValidAddressForNetwork : public boost::static_visitor<bool> {
|
||||
public:
|
||||
IsValidAddressForNetwork(uint32_t consensusBranchId) : branchId(consensusBranchId) {}
|
||||
|
||||
bool operator()(const libzcash::SproutPaymentAddress &addr) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(const libzcash::InvalidEncoding &addr) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "sodium.h"
|
||||
#include "streams.h"
|
||||
#include "txdb.h"
|
||||
#include "utiltest.h"
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
#include "zcbenchmarks.h"
|
||||
@@ -41,7 +40,7 @@ void pre_wallet_load()
|
||||
{
|
||||
LogPrintf("%s: In progress...\n", __func__);
|
||||
if (ShutdownRequested())
|
||||
throw new std::runtime_error("The node is shutting down");
|
||||
throw new std::runtime_error("The Hush node is shutting down");
|
||||
|
||||
if (pwalletMain)
|
||||
pwalletMain->Flush(false);
|
||||
@@ -93,37 +92,6 @@ double benchmark_sleep()
|
||||
return timer_stop(tv_start);
|
||||
}
|
||||
|
||||
std::vector<double> benchmark_create_joinsplit_threaded(int nThreads)
|
||||
{
|
||||
std::vector<double> ret;
|
||||
std::vector<std::future<double>> tasks;
|
||||
std::vector<std::thread> threads;
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
std::packaged_task<double(void)> task(&benchmark_create_joinsplit);
|
||||
tasks.emplace_back(task.get_future());
|
||||
threads.emplace_back(std::move(task));
|
||||
}
|
||||
std::future_status status;
|
||||
for (auto it = tasks.begin(); it != tasks.end(); it++) {
|
||||
it->wait();
|
||||
ret.push_back(it->get());
|
||||
}
|
||||
for (auto it = threads.begin(); it != threads.end(); it++) {
|
||||
it->join();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
double benchmark_verify_joinsplit(const JSDescription &joinsplit)
|
||||
{
|
||||
struct timeval tv_start;
|
||||
timer_start(tv_start);
|
||||
uint256 joinSplitPubKey;
|
||||
auto verifier = libzcash::ProofVerifier::Strict();
|
||||
joinsplit.Verify(*pzcashParams, verifier, joinSplitPubKey);
|
||||
return timer_stop(tv_start);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MINING
|
||||
double benchmark_solve_equihash()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user