Ensure we don’t make Orchard change pre-NU5
Co-authored-by: Kris Nuttycombe <kris@nutty.land>
This commit is contained in:
parent
c8fed15f19
commit
11721906fd
|
@ -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();
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue