Additional z_sendmany test cases
Also improve error messages.
This commit is contained in:
parent
62ae44a131
commit
1f72b42b81
|
@ -339,6 +339,10 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
||||||
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy)
|
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy)
|
||||||
wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', msg)
|
wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', msg)
|
||||||
|
|
||||||
|
# If we try to send just a bit less than we have, it will fail, complaining about dust
|
||||||
|
opid = self.nodes[1].z_sendmany(n1ua0, [{"address":n0ua0, "amount":3.9999999}], 1, 0, 'AllowLinkingAccountAddresses')
|
||||||
|
wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', 'Insufficient funds: have 4.00, need 0.00000044 more to avoid creating invalid change output 0.0000001 (dust threshold is 0.00000054).')
|
||||||
|
|
||||||
# Once we provide a sufficiently-weak policy, the transaction succeeds.
|
# Once we provide a sufficiently-weak policy, the transaction succeeds.
|
||||||
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'AllowLinkingAccountAddresses')
|
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'AllowLinkingAccountAddresses')
|
||||||
wait_and_assert_operationid_status(self.nodes[1], opid)
|
wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||||
|
@ -359,6 +363,20 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
||||||
assert_equal(self.nodes[1].z_getbalance(n1ua0), 1)
|
assert_equal(self.nodes[1].z_getbalance(n1ua0), 1)
|
||||||
assert_equal(self.nodes[1].z_getbalance(n1ua1), 1)
|
assert_equal(self.nodes[1].z_getbalance(n1ua1), 1)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test Orchard-only UA before NU5
|
||||||
|
#
|
||||||
|
|
||||||
|
n0orchard_only = self.nodes[0].z_getaddressforaccount(n0account0, ["orchard"])['address']
|
||||||
|
recipients = [{"address":n0orchard_only, "amount":1}]
|
||||||
|
for (policy, msg) in [
|
||||||
|
('FullPrivacy', 'Could not send to a shielded receiver of a unified address without spending funds from a different pool, which would reveal transaction amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedAmounts` or weaker if you wish to allow this transaction to proceed anyway.'),
|
||||||
|
('AllowRevealedAmounts', 'This transaction would send to a transparent receiver of a unified address, which is not enabled by default because it will publicly reveal transaction recipients and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedRecipients` or weaker if you wish to allow this transaction to proceed anyway.'),
|
||||||
|
('AllowRevealedRecipients', 'Could not send to an Orchard-only receiver, despite a lax privacy policy. Either there are insufficent non-Sprout funds, or NU5 has not been activated yet.'),
|
||||||
|
]:
|
||||||
|
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy)
|
||||||
|
wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', msg)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test NoPrivacy policy
|
# Test NoPrivacy policy
|
||||||
#
|
#
|
||||||
|
@ -392,6 +410,19 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
||||||
self.nodes[1].generate(10)
|
self.nodes[1].generate(10)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test Orchard-only UA with insufficient non-Sprout funds
|
||||||
|
#
|
||||||
|
|
||||||
|
recipients = [{"address":n0orchard_only, "amount":100}]
|
||||||
|
for (policy, msg) in [
|
||||||
|
('FullPrivacy', 'Could not send to a shielded receiver of a unified address without spending funds from a different pool, which would reveal transaction amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedAmounts` or weaker if you wish to allow this transaction to proceed anyway.'),
|
||||||
|
('AllowRevealedAmounts', 'This transaction would send to a transparent receiver of a unified address, which is not enabled by default because it will publicly reveal transaction recipients and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedRecipients` or weaker if you wish to allow this transaction to proceed anyway.'),
|
||||||
|
('AllowRevealedRecipients', 'Could not send to an Orchard-only receiver, despite a lax privacy policy. Either there are insufficent non-Sprout funds, or NU5 has not been activated yet.'),
|
||||||
|
]:
|
||||||
|
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy)
|
||||||
|
wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', msg)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test AllowRevealedAmounts policy
|
# Test AllowRevealedAmounts policy
|
||||||
#
|
#
|
||||||
|
|
|
@ -139,14 +139,24 @@ void ThrowInputSelectionError(
|
||||||
FormatMoney(err.available - err.required)));
|
FormatMoney(err.available - err.required)));
|
||||||
},
|
},
|
||||||
[](const ExcessOrchardActionsError& err) {
|
[](const ExcessOrchardActionsError& err) {
|
||||||
|
std::string side;
|
||||||
|
switch (err.side) {
|
||||||
|
case ActionSide::Input:
|
||||||
|
side = "inputs";
|
||||||
|
case ActionSide::Output:
|
||||||
|
side = "outputs";
|
||||||
|
case ActionSide::Both:
|
||||||
|
side = "actions";
|
||||||
|
};
|
||||||
throw JSONRPCError(
|
throw JSONRPCError(
|
||||||
RPC_INVALID_PARAMETER,
|
RPC_INVALID_PARAMETER,
|
||||||
strprintf(
|
strprintf(
|
||||||
"Attempting to spend %u Orchard notes would exceed the current limit "
|
"Including %u Orchard %s would exceed the current limit "
|
||||||
"of %u notes, which exists to prevent memory exhaustion. Restart with "
|
"of %u notes, which exists to prevent memory exhaustion. Restart with "
|
||||||
"`-orchardactionlimit=N` where N >= %u to allow the wallet to attempt "
|
"`-orchardactionlimit=N` where N >= %u to allow the wallet to attempt "
|
||||||
"to construct this transaction.",
|
"to construct this transaction.",
|
||||||
err.orchardNotes,
|
err.orchardNotes,
|
||||||
|
side,
|
||||||
err.maxNotes,
|
err.maxNotes,
|
||||||
err.orchardNotes));
|
err.orchardNotes));
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,7 +307,10 @@ InputSelectionResult WalletTxBuilder::ResolveInputsAndPayments(
|
||||||
auto resolved = Payments(resolvedPayments);
|
auto resolved = Payments(resolvedPayments);
|
||||||
|
|
||||||
if (orchardOutputs > this->maxOrchardActions) {
|
if (orchardOutputs > this->maxOrchardActions) {
|
||||||
return ExcessOrchardActionsError(orchardOutputs, this->maxOrchardActions);
|
return ExcessOrchardActionsError(
|
||||||
|
ActionSide::Output,
|
||||||
|
orchardOutputs,
|
||||||
|
this->maxOrchardActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the dust threshold so that we can select enough inputs to avoid
|
// Set the dust threshold so that we can select enough inputs to avoid
|
||||||
|
@ -343,7 +346,10 @@ InputSelectionResult WalletTxBuilder::ResolveInputsAndPayments(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spendableMut.orchardNoteMetadata.size() > this->maxOrchardActions) {
|
if (spendableMut.orchardNoteMetadata.size() > this->maxOrchardActions) {
|
||||||
return ExcessOrchardActionsError(spendableMut.orchardNoteMetadata.size(), this->maxOrchardActions);
|
return ExcessOrchardActionsError(
|
||||||
|
ActionSide::Input,
|
||||||
|
spendableMut.orchardNoteMetadata.size(),
|
||||||
|
this->maxOrchardActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
return InputSelection(resolved, anchorHeight);
|
return InputSelection(resolved, anchorHeight);
|
||||||
|
|
|
@ -260,12 +260,20 @@ public:
|
||||||
available(available), required(required) { }
|
available(available), required(required) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ActionSide {
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
Both,
|
||||||
|
};
|
||||||
|
|
||||||
class ExcessOrchardActionsError {
|
class ExcessOrchardActionsError {
|
||||||
public:
|
public:
|
||||||
|
ActionSide side;
|
||||||
uint32_t orchardNotes;
|
uint32_t orchardNotes;
|
||||||
uint32_t maxNotes;
|
uint32_t maxNotes;
|
||||||
|
|
||||||
ExcessOrchardActionsError(uint32_t orchardNotes, uint32_t maxNotes): orchardNotes(orchardNotes), maxNotes(maxNotes) { }
|
ExcessOrchardActionsError(ActionSide side, uint32_t orchardNotes, uint32_t maxNotes):
|
||||||
|
side(side), orchardNotes(orchardNotes), maxNotes(maxNotes) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::variant<
|
typedef std::variant<
|
||||||
|
|
Loading…
Reference in New Issue