Merge remote-tracking branch 'zcash/master' into rebase2
# Conflicts: # .travis.yml # Makefile.am # README.md # configure.ac # depends/Makefile # depends/builders/darwin.mk # depends/funcs.mk # depends/hosts/darwin.mk # depends/packages/googlemock.mk # depends/packages/googletest.mk # depends/packages/libsnark.mk # depends/packages/libsodium.mk # depends/packages/packages.mk # depends/packages/rust.mk # src/Makefile.am # src/Makefile.gtest.include # src/chainparams.cpp # src/chainparams.h # src/checkpoints.h # src/clientversion.h # src/coins.cpp # src/consensus/consensus.h # src/gtest/test_mempool.cpp # src/httprpc.cpp # src/init.cpp # src/komodo-tx.cpp # src/main.cpp # src/miner.cpp # src/policy/fees.cpp # src/policy/fees.h # src/rpcmining.cpp # src/rpcrawtransaction.cpp # src/rpcserver.cpp # src/test/policyestimator_tests.cpp # src/test/rpc_wallet_tests.cpp # src/test/transaction_tests.cpp # src/txdb.cpp # src/txmempool.cpp # src/wallet/asyncrpcoperation_sendmany.cpp # src/wallet/rpcwallet.cpp # src/wallet/wallet.cpp # src/wallet/wallet.h # src/zcash/CreateJoinSplit.cpp # zcutil/build.sh
This commit is contained in:
@@ -8,7 +8,9 @@
|
||||
#include "base58.h"
|
||||
#include "checkpoints.h"
|
||||
#include "coincontrol.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
#include "net.h"
|
||||
@@ -111,6 +113,10 @@ bool CWallet::AddZKey(const libzcash::SpendingKey &key)
|
||||
if (!CCryptoKeyStore::AddSpendingKey(key))
|
||||
return false;
|
||||
|
||||
// check if we need to remove from viewing keys
|
||||
if (HaveViewingKey(addr))
|
||||
RemoveViewingKey(key.viewing_key());
|
||||
|
||||
if (!fFileBacked)
|
||||
return true;
|
||||
|
||||
@@ -194,10 +200,10 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
|
||||
|
||||
|
||||
bool CWallet::AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
|
||||
const libzcash::ViewingKey &vk,
|
||||
const libzcash::ReceivingKey &rk,
|
||||
const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
if (!CCryptoKeyStore::AddCryptedSpendingKey(address, vk, vchCryptedSecret))
|
||||
if (!CCryptoKeyStore::AddCryptedSpendingKey(address, rk, vchCryptedSecret))
|
||||
return false;
|
||||
if (!fFileBacked)
|
||||
return true;
|
||||
@@ -205,12 +211,12 @@ bool CWallet::AddCryptedSpendingKey(const libzcash::PaymentAddress &address,
|
||||
LOCK(cs_wallet);
|
||||
if (pwalletdbEncryption) {
|
||||
return pwalletdbEncryption->WriteCryptedZKey(address,
|
||||
vk,
|
||||
rk,
|
||||
vchCryptedSecret,
|
||||
mapZKeyMetadata[address]);
|
||||
} else {
|
||||
return CWalletDB(strWalletFile).WriteCryptedZKey(address,
|
||||
vk,
|
||||
rk,
|
||||
vchCryptedSecret,
|
||||
mapZKeyMetadata[address]);
|
||||
}
|
||||
@@ -240,9 +246,9 @@ bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigne
|
||||
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
|
||||
}
|
||||
|
||||
bool CWallet::LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ViewingKey &vk, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
bool CWallet::LoadCryptedZKey(const libzcash::PaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
return CCryptoKeyStore::AddCryptedSpendingKey(addr, vk, vchCryptedSecret);
|
||||
return CCryptoKeyStore::AddCryptedSpendingKey(addr, rk, vchCryptedSecret);
|
||||
}
|
||||
|
||||
bool CWallet::LoadZKey(const libzcash::SpendingKey &key)
|
||||
@@ -250,6 +256,38 @@ bool CWallet::LoadZKey(const libzcash::SpendingKey &key)
|
||||
return CCryptoKeyStore::AddSpendingKey(key);
|
||||
}
|
||||
|
||||
bool CWallet::AddViewingKey(const libzcash::ViewingKey &vk)
|
||||
{
|
||||
if (!CCryptoKeyStore::AddViewingKey(vk)) {
|
||||
return false;
|
||||
}
|
||||
nTimeFirstKey = 1; // No birthday information for viewing keys.
|
||||
if (!fFileBacked) {
|
||||
return true;
|
||||
}
|
||||
return CWalletDB(strWalletFile).WriteViewingKey(vk);
|
||||
}
|
||||
|
||||
bool CWallet::RemoveViewingKey(const libzcash::ViewingKey &vk)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
if (!CCryptoKeyStore::RemoveViewingKey(vk)) {
|
||||
return false;
|
||||
}
|
||||
if (fFileBacked) {
|
||||
if (!CWalletDB(strWalletFile).EraseViewingKey(vk)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::LoadViewingKey(const libzcash::ViewingKey &vk)
|
||||
{
|
||||
return CCryptoKeyStore::AddViewingKey(vk);
|
||||
}
|
||||
|
||||
bool CWallet::AddCScript(const CScript& redeemScript)
|
||||
{
|
||||
if (!CCryptoKeyStore::AddCScript(redeemScript))
|
||||
@@ -963,7 +1001,8 @@ void CWallet::MarkDirty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that every note in the wallet has a cached nullifier.
|
||||
* Ensure that every note in the wallet (for which we possess a spending key)
|
||||
* has a cached nullifier.
|
||||
*/
|
||||
bool CWallet::UpdateNullifierNoteMap()
|
||||
{
|
||||
@@ -977,16 +1016,17 @@ bool CWallet::UpdateNullifierNoteMap()
|
||||
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
|
||||
for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
|
||||
if (!item.second.nullifier) {
|
||||
auto i = item.first.js;
|
||||
GetNoteDecryptor(item.second.address, dec);
|
||||
auto hSig = wtxItem.second.vjoinsplit[i].h_sig(
|
||||
*pzcashParams, wtxItem.second.joinSplitPubKey);
|
||||
item.second.nullifier = GetNoteNullifier(
|
||||
wtxItem.second.vjoinsplit[i],
|
||||
item.second.address,
|
||||
dec,
|
||||
hSig,
|
||||
item.first.n);
|
||||
if (GetNoteDecryptor(item.second.address, dec)) {
|
||||
auto i = item.first.js;
|
||||
auto hSig = wtxItem.second.vjoinsplit[i].h_sig(
|
||||
*pzcashParams, wtxItem.second.joinSplitPubKey);
|
||||
item.second.nullifier = GetNoteNullifier(
|
||||
wtxItem.second.vjoinsplit[i],
|
||||
item.second.address,
|
||||
dec,
|
||||
hSig,
|
||||
item.first.n);
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateNullifierNoteMapWithTx(wtxItem.second);
|
||||
@@ -1248,7 +1288,9 @@ boost::optional<uint256> CWallet::GetNoteNullifier(const JSDescription& jsdesc,
|
||||
hSig,
|
||||
(unsigned char) n);
|
||||
auto note = note_pt.note(address);
|
||||
// SpendingKeys are only available if the wallet is unlocked
|
||||
// SpendingKeys are only available if:
|
||||
// - We have them (this isn't a viewing key)
|
||||
// - The wallet is unlocked
|
||||
libzcash::SpendingKey key;
|
||||
if (GetSpendingKey(address, key)) {
|
||||
ret = note.nullifier(key);
|
||||
@@ -2580,6 +2622,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
|
||||
|
||||
CReserveKey reservekey(this);
|
||||
CWalletTx wtx;
|
||||
|
||||
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
|
||||
return false;
|
||||
|
||||
@@ -2629,36 +2672,23 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
|
||||
wtxNew.fTimeReceivedIsTxTime = true;
|
||||
wtxNew.BindWallet(this);
|
||||
CMutableTransaction txNew;
|
||||
|
||||
if ( 0 )
|
||||
{
|
||||
// Discourage fee sniping.
|
||||
//
|
||||
// However because of a off-by-one-error in previous versions we need to
|
||||
// neuter it by setting nLockTime to at least one less than nBestHeight.
|
||||
// Secondly currently propagation of transactions created for block heights
|
||||
// corresponding to blocks that were just mined may be iffy - transactions
|
||||
// aren't re-accepted into the mempool - we additionally neuter the code by
|
||||
// going ten blocks back. Doesn't yet do anything for sniping, but does act
|
||||
// to shake out wallet bugs like not showing nLockTime'd transactions at
|
||||
// all.
|
||||
txNew.nLockTime = std::max(0, chainActive.Height() - 10);
|
||||
|
||||
// Secondly occasionally randomly pick a nLockTime even further back, so
|
||||
// that transactions that are delayed after signing for whatever reason,
|
||||
// e.g. high-latency mix networks and some CoinJoin implementations, have
|
||||
// better privacy.
|
||||
if (GetRandInt(10) == 0)
|
||||
txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
|
||||
|
||||
assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
|
||||
assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
|
||||
}
|
||||
else
|
||||
{
|
||||
int nextBlockHeight = chainActive.Height() + 1;
|
||||
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(
|
||||
Params().GetConsensus(), nextBlockHeight);
|
||||
txNew.nLockTime = (uint32_t)chainActive.Tip()->nTime + 1; // set to a time close to now
|
||||
|
||||
// Activates after Overwinter network upgrade
|
||||
// Set nExpiryHeight to expiryDelta (default 20) blocks past current block height
|
||||
if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER))
|
||||
{
|
||||
if (nextBlockHeight + expiryDelta >= TX_EXPIRY_HEIGHT_THRESHOLD){
|
||||
strFailReason = _("nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD.");
|
||||
return false;
|
||||
} else {
|
||||
txNew.nExpiryHeight = nextBlockHeight + expiryDelta;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
{
|
||||
@@ -2838,6 +2868,19 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
|
||||
std::numeric_limits<unsigned int>::max()-1));
|
||||
|
||||
// Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
|
||||
size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
|
||||
if (limit > 0) {
|
||||
size_t n = txNew.vin.size();
|
||||
if (n > limit) {
|
||||
strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the current consensus branch ID
|
||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||
|
||||
// Sign
|
||||
int nIn = 0;
|
||||
CTransaction txNewConst(txNew);
|
||||
@@ -2845,17 +2888,20 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
{
|
||||
bool signSuccess;
|
||||
const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
|
||||
CScript& scriptSigRes = txNew.vin[nIn].scriptSig;
|
||||
SignatureData sigdata;
|
||||
if (sign)
|
||||
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, SIGHASH_ALL), scriptPubKey, scriptSigRes);
|
||||
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId);
|
||||
else
|
||||
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, scriptSigRes);
|
||||
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
|
||||
|
||||
if (!signSuccess)
|
||||
{
|
||||
strFailReason = _("Signing transaction failed");
|
||||
return false;
|
||||
} else {
|
||||
UpdateTransaction(txNew, nIn, sigdata);
|
||||
}
|
||||
|
||||
nIn++;
|
||||
}
|
||||
|
||||
@@ -3724,15 +3770,28 @@ 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)
|
||||
void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent, bool ignoreUnspendable)
|
||||
{
|
||||
bool fFilterAddress = false;
|
||||
libzcash::PaymentAddress filterPaymentAddress;
|
||||
std::set<PaymentAddress> filterAddresses;
|
||||
|
||||
if (address.length() > 0) {
|
||||
filterPaymentAddress = CZCPaymentAddress(address).Get();
|
||||
fFilterAddress = true;
|
||||
filterAddresses.insert(CZCPaymentAddress(address).Get());
|
||||
}
|
||||
|
||||
GetFilteredNotes(outEntries, filterAddresses, minDepth, ignoreSpent, ignoreUnspendable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find notes in the wallet filtered by payment addresses, 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::set<PaymentAddress>& filterAddresses,
|
||||
int minDepth,
|
||||
bool ignoreSpent,
|
||||
bool ignoreUnspendable)
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
|
||||
for (auto & p : mapWallet) {
|
||||
@@ -3753,7 +3812,7 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
|
||||
PaymentAddress pa = nd.address;
|
||||
|
||||
// skip notes which belong to a different payment address in the wallet
|
||||
if (fFilterAddress && !(pa == filterPaymentAddress)) {
|
||||
if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3762,6 +3821,11 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip notes which cannot be spent
|
||||
if (ignoreUnspendable && !HaveSpendingKey(pa)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int i = jsop.js; // Index into CTransaction.vjoinsplit
|
||||
int j = jsop.n; // Index into JSDescription.ciphertexts
|
||||
|
||||
@@ -3782,7 +3846,7 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
|
||||
hSig,
|
||||
(unsigned char) j);
|
||||
|
||||
outEntries.push_back(CNotePlaintextEntry{jsop, plaintext});
|
||||
outEntries.push_back(CNotePlaintextEntry{jsop, pa, plaintext});
|
||||
|
||||
} catch (const note_decryption_failed &err) {
|
||||
// Couldn't decrypt with this spending key
|
||||
|
||||
Reference in New Issue
Block a user