Ensure we don’t make Orchard change pre-NU5

Co-authored-by: Kris Nuttycombe <kris@nutty.land>
This commit is contained in:
Greg Pfeil 2023-01-23 15:57:05 -07:00
parent c8fed15f19
commit 11721906fd
No known key found for this signature in database
GPG Key ID: 1193ACD196ED61F2
5 changed files with 22 additions and 17 deletions

View File

@ -284,7 +284,7 @@ TEST(WalletRPCTests, RPCZsendmanyTaddrToSapling)
pwalletMain->LoadWalletTx(wtx); pwalletMain->LoadWalletTx(wtx);
// Context that z_sendmany requires // Context that z_sendmany requires
auto builder = WalletTxBuilder(*pwalletMain, minRelayTxFee); auto builder = WalletTxBuilder(Params(), *pwalletMain, minRelayTxFee);
mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight, false); mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight, false);
auto selector = pwalletMain->ZTXOSelectorForAddress(taddr, true, false, TransactionStrategy(PrivacyPolicy::FullPrivacy)).value(); auto selector = pwalletMain->ZTXOSelectorForAddress(taddr, true, false, TransactionStrategy(PrivacyPolicy::FullPrivacy)).value();

View File

@ -4982,7 +4982,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
// Create operation and add to global queue // Create operation and add to global queue
auto nAnchorDepth = std::min((unsigned int) nMinDepth, nAnchorConfirmations); auto nAnchorDepth = std::min((unsigned int) nMinDepth, nAnchorConfirmations);
WalletTxBuilder builder(*pwalletMain, minRelayTxFee); WalletTxBuilder builder(Params(), *pwalletMain, minRelayTxFee);
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue(); std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation( std::shared_ptr<AsyncRPCOperation> operation(

View File

@ -1239,7 +1239,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
// there are no utxos to spend // there are no utxos to spend
{ {
auto selector = pwalletMain->ZTXOSelectorForAddress(taddr1, true, false, FULL_PRIVACY).value(); auto selector = pwalletMain->ZTXOSelectorForAddress(taddr1, true, false, FULL_PRIVACY).value();
WalletTxBuilder builder(*pwalletMain, minRelayTxFee); WalletTxBuilder builder(Params(), *pwalletMain, minRelayTxFee);
std::vector<Payment> recipients = { Payment(zaddr1, 100*COIN, Memo::FromHexOrThrow("DEADBEEF")) }; std::vector<Payment> recipients = { Payment(zaddr1, 100*COIN, Memo::FromHexOrThrow("DEADBEEF")) };
TransactionStrategy strategy; TransactionStrategy strategy;
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, 1, strategy)); std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, 1, strategy));
@ -1252,7 +1252,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
// there are no unspent notes to spend // there are no unspent notes to spend
{ {
auto selector = pwalletMain->ZTXOSelectorForAddress(zaddr1, true, false, FULL_PRIVACY).value(); auto selector = pwalletMain->ZTXOSelectorForAddress(zaddr1, true, false, FULL_PRIVACY).value();
WalletTxBuilder builder(*pwalletMain, minRelayTxFee); WalletTxBuilder builder(Params(), *pwalletMain, minRelayTxFee);
std::vector<Payment> recipients = { Payment(taddr1, 100*COIN, Memo::FromHexOrThrow("DEADBEEF")) }; std::vector<Payment> recipients = { Payment(taddr1, 100*COIN, Memo::FromHexOrThrow("DEADBEEF")) };
TransactionStrategy strategy(PrivacyPolicy::AllowRevealedRecipients); TransactionStrategy strategy(PrivacyPolicy::AllowRevealedRecipients);
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, 1, strategy)); std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, 1, strategy));

View File

@ -6,7 +6,7 @@
using namespace libzcash; using namespace libzcash;
int GetAnchorHeight(const CChain& chain, int anchorConfirmations) int GetAnchorHeight(const CChain& chain, uint32_t anchorConfirmations)
{ {
int nextBlockHeight = chain.Height() + 1; int nextBlockHeight = chain.Height() + 1;
return nextBlockHeight - anchorConfirmations; return nextBlockHeight - anchorConfirmations;
@ -23,7 +23,8 @@ PrepareTransactionResult WalletTxBuilder::PrepareTransaction(
{ {
assert(fee < MAX_MONEY); assert(fee < MAX_MONEY);
auto selected = ResolveInputsAndPayments(spendable, payments, chain, strategy, fee, anchorConfirmations); int anchorHeight = GetAnchorHeight(chain, anchorConfirmations);
auto selected = ResolveInputsAndPayments(selector, spendable, payments, chain, strategy, fee, anchorHeight);
if (std::holds_alternative<InputSelectionError>(selected)) { if (std::holds_alternative<InputSelectionError>(selected)) {
return std::get<InputSelectionError>(selected); return std::get<InputSelectionError>(selected);
} }
@ -68,7 +69,8 @@ PrepareTransactionResult WalletTxBuilder::PrepareTransaction(
} }
break; break;
case ReceiverType::Orchard: case ReceiverType::Orchard:
if (!spendable.orchardNoteMetadata.empty() || strategy.AllowRevealedAmounts()) { if (params.GetConsensus().NetworkUpgradeActive(anchorHeight, Consensus::UPGRADE_NU5)
&& (!spendable.orchardNoteMetadata.empty() || strategy.AllowRevealedAmounts())) {
result.insert(OutputPool::Orchard); result.insert(OutputPool::Orchard);
} }
break; break;
@ -152,7 +154,7 @@ PrepareTransactionResult WalletTxBuilder::PrepareTransaction(
} }
}, },
[&](const libzcash::UnifiedFullViewingKey& fvk) { [&](const libzcash::UnifiedFullViewingKey& fvk) {
auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(Params(), fvk); auto zufvk = ZcashdUnifiedFullViewingKey::FromUnifiedFullViewingKey(params, fvk);
auto sendTo = zufvk.GetChangeAddress( auto sendTo = zufvk.GetChangeAddress(
allowedChangeTypes(fvk.GetKnownReceiverTypes())); allowedChangeTypes(fvk.GetKnownReceiverTypes()));
if (sendTo.has_value()) { if (sendTo.has_value()) {
@ -189,7 +191,7 @@ PrepareTransactionResult WalletTxBuilder::PrepareTransaction(
fee, fee,
ovks.first, ovks.first,
ovks.second, ovks.second,
GetAnchorHeight(chain, anchorConfirmations)); anchorHeight);
} }
Payments InputSelection::GetPayments() const { Payments InputSelection::GetPayments() const {
@ -232,12 +234,13 @@ bool WalletTxBuilder::AllowTransparentCoinbase(
} }
InputSelectionResult WalletTxBuilder::ResolveInputsAndPayments( InputSelectionResult WalletTxBuilder::ResolveInputsAndPayments(
const ZTXOSelector& selector,
SpendableInputs& spendableMut, SpendableInputs& spendableMut,
const std::vector<Payment>& payments, const std::vector<Payment>& payments,
const CChain& chain, const CChain& chain,
TransactionStrategy strategy, TransactionStrategy strategy,
CAmount fee, CAmount fee,
uint32_t anchorConfirmations) const int anchorHeight) const
{ {
LOCK2(cs_main, wallet.cs_wallet); LOCK2(cs_main, wallet.cs_wallet);
@ -259,10 +262,11 @@ InputSelectionResult WalletTxBuilder::ResolveInputsAndPayments(
// we can only select Orchard addresses if there are sufficient non-Sprout // we can only select Orchard addresses if there are sufficient non-Sprout
// funds to cover the total payments + fee. // funds to cover the total payments + fee.
bool canResolveOrchard = spendableMut.Total() - spendableMut.GetSproutBalance() >= targetAmount; bool canResolveOrchard =
params.GetConsensus().NetworkUpgradeActive(anchorHeight, Consensus::UPGRADE_NU5)
&& spendableMut.Total() - spendableMut.GetSproutBalance() >= targetAmount;
std::vector<ResolvedPayment> resolvedPayments; std::vector<ResolvedPayment> resolvedPayments;
std::optional<AddressResolutionError> resolutionError; std::optional<AddressResolutionError> resolutionError;
int anchorHeight = GetAnchorHeight(chain, anchorConfirmations);
for (const auto& payment : payments) { for (const auto& payment : payments) {
std::visit(match { std::visit(match {
[&](const CKeyID& p2pkh) { [&](const CKeyID& p2pkh) {
@ -297,8 +301,7 @@ InputSelectionResult WalletTxBuilder::ResolveInputsAndPayments(
}, },
[&](const UnifiedAddress& ua) { [&](const UnifiedAddress& ua) {
bool resolved{false}; bool resolved{false};
if (Params().GetConsensus().NetworkUpgradeActive(anchorHeight, Consensus::UPGRADE_NU5) if (canResolveOrchard
&& canResolveOrchard
&& ua.GetOrchardReceiver().has_value() && ua.GetOrchardReceiver().has_value()
&& (strategy.AllowRevealedAmounts() || payment.GetAmount() < maxOrchardAvailable) && (strategy.AllowRevealedAmounts() || payment.GetAmount() < maxOrchardAvailable)
) { ) {

View File

@ -292,6 +292,7 @@ typedef std::variant<
class WalletTxBuilder { class WalletTxBuilder {
private: private:
const CChainParams& params;
const CWallet& wallet; const CWallet& wallet;
CFeeRate minRelayFee; CFeeRate minRelayFee;
uint32_t maxOrchardActions; uint32_t maxOrchardActions;
@ -307,12 +308,13 @@ private:
* and the requested transaction strategy. * and the requested transaction strategy.
*/ */
InputSelectionResult ResolveInputsAndPayments( InputSelectionResult ResolveInputsAndPayments(
const ZTXOSelector& selector,
SpendableInputs& spendable, SpendableInputs& spendable,
const std::vector<Payment>& payments, const std::vector<Payment>& payments,
const CChain& chain, const CChain& chain,
TransactionStrategy strategy, TransactionStrategy strategy,
CAmount fee, CAmount fee,
uint32_t anchorConfirmations) const; int anchorHeight) const;
/** /**
* Compute the internal and external OVKs to use in transaction construction, given * Compute the internal and external OVKs to use in transaction construction, given
* the spendable inputs. * the spendable inputs.
@ -322,8 +324,8 @@ private:
const SpendableInputs& spendable) const; const SpendableInputs& spendable) const;
public: public:
WalletTxBuilder(const CWallet& wallet, CFeeRate minRelayFee): WalletTxBuilder(const CChainParams& params, const CWallet& wallet, CFeeRate minRelayFee):
wallet(wallet), minRelayFee(minRelayFee), maxOrchardActions(nOrchardActionLimit) {} params(params), wallet(wallet), minRelayFee(minRelayFee), maxOrchardActions(nOrchardActionLimit) {}
static bool AllowTransparentCoinbase( static bool AllowTransparentCoinbase(
const std::vector<Payment>& payments, const std::vector<Payment>& payments,