z_sendmany: Expand `privacyPolicy` cases
We now have a full roster of privacy policies. We can graph the relationships between the policies; arrows point from more-private to less-private, and each policy is permitted to reveal information covered by all policies pointing to it (in addition to the extra information it is permitted to reveal). FullPrivacy v AllowRevealedAmounts v v AllowRevealedRecipients ---- AllowRevealedSenders v / v AllowFullyTransparent <- AllowLinkingAccountAddresses v v NoPrivacy The synthetic `LegacyCompat` policy now uses the `AllowFullyTransparent` policy for backwards compatibility, and the `FullPrivacy` policy if the sender or recipients involve Unified Addresses. Closes zcash/zcash#5677. Closes zcash/zcash#5678.
This commit is contained in:
parent
1505121877
commit
65cb79e023
|
@ -88,7 +88,8 @@ Wallet
|
|||
information than the given strategy permits, `z_sendmany` will return an
|
||||
error. The parameter defaults to `LegacyCompat`, which applies the most
|
||||
restrictive strategy `FullPrivacy` when a Unified Address is present as the
|
||||
sender or a recipient, and otherwise preserves existing behaviour.
|
||||
sender or a recipient, and otherwise preserves existing behaviour (which
|
||||
corresponds to the `AllowFullyTransparent` policy).
|
||||
|
||||
- Since Sprout outputs are no longer created (with the exception of change)
|
||||
'z_sendmany' no longer generates payment disclosures (which were only
|
||||
|
|
|
@ -70,7 +70,7 @@ class OrchardReorgTest(BitcoinTestFramework):
|
|||
|
||||
# Create an Orchard note.
|
||||
recipients = [{'address': ua, 'amount': Decimal('12.5')}]
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
wait_and_assert_operationid_status(self.nodes[0], opid)
|
||||
|
||||
# After mining a block, finalorchardroot should have changed.
|
||||
|
@ -95,7 +95,7 @@ class OrchardReorgTest(BitcoinTestFramework):
|
|||
|
||||
# Create another Orchard note on node 0.
|
||||
recipients = [{'address': ua, 'amount': Decimal('12.5')}]
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
wait_and_assert_operationid_status(self.nodes[0], opid)
|
||||
|
||||
# Mine two blocks on node 0.
|
||||
|
|
|
@ -118,7 +118,7 @@ class WalletAccountsTest(BitcoinTestFramework):
|
|||
# Send coinbase funds to the UA.
|
||||
print('Sending coinbase funds to account')
|
||||
recipients = [{'address': ua0, 'amount': Decimal('10')}]
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
txid = wait_and_assert_operationid_status(self.nodes[0], opid)
|
||||
|
||||
# The wallet should detect the new note as belonging to the UA.
|
||||
|
@ -169,7 +169,7 @@ class WalletAccountsTest(BitcoinTestFramework):
|
|||
# Send more coinbase funds to the UA.
|
||||
print('Sending coinbase funds to account')
|
||||
recipients = [{'address': ua0, 'amount': Decimal('10')}]
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
|
||||
opid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
txid = wait_and_assert_operationid_status(self.nodes[0], opid)
|
||||
|
||||
# The wallet should detect the new note as belonging to the UA.
|
||||
|
|
|
@ -54,7 +54,7 @@ class WalletOrchardTest(BitcoinTestFramework):
|
|||
saplingAddr2 = self.nodes[2].z_listunifiedreceivers(ua2)['sapling']
|
||||
|
||||
recipients = [{"address": saplingAddr2, "amount": Decimal('10')}]
|
||||
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
|
||||
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
|
||||
# Mine the tx & activate NU5
|
||||
|
@ -70,7 +70,7 @@ class WalletOrchardTest(BitcoinTestFramework):
|
|||
# Node 0 shields some funds
|
||||
# t-coinbase -> Orchard
|
||||
recipients = [{"address": ua1, "amount": Decimal('10')}]
|
||||
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
|
||||
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
|
||||
self.sync_all()
|
||||
|
@ -86,7 +86,7 @@ class WalletOrchardTest(BitcoinTestFramework):
|
|||
|
||||
# Send another tx to ua1
|
||||
recipients = [{"address": ua1, "amount": Decimal('10')}]
|
||||
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0)
|
||||
myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients, 1, 0, 'AllowRevealedSenders')
|
||||
wait_and_assert_operationid_status(self.nodes[0], myopid)
|
||||
|
||||
# Mine the tx & generate a majority chain on the 0/1 side of the split
|
||||
|
|
|
@ -4,8 +4,15 @@
|
|||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_greater_than, connect_nodes_bi, \
|
||||
DEFAULT_FEE, start_nodes, wait_and_assert_operationid_status
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
assert_greater_than,
|
||||
assert_raises_message,
|
||||
connect_nodes_bi,
|
||||
DEFAULT_FEE,
|
||||
start_nodes,
|
||||
wait_and_assert_operationid_status,
|
||||
)
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.mininode import COIN
|
||||
from decimal import Decimal
|
||||
|
@ -164,9 +171,36 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
|||
|
||||
# Change went to a fresh address, so use `ANY_TADDR` which
|
||||
# should hold the rest of our transparent funds.
|
||||
source = 'ANY_TADDR'
|
||||
recipients = []
|
||||
recipients.append({"address":n0ua0, "amount":10})
|
||||
opid = self.nodes[2].z_sendmany('ANY_TADDR', recipients, 1, 0)
|
||||
|
||||
# If we attempt to spend with the default privacy policy, z_sendmany
|
||||
# fails because it needs to spend transparent coins in a transaction
|
||||
# involving a Unified Address.
|
||||
revealed_senders_msg = 'This transaction requires selecting transparent coins, which is not enabled by default because it will publicly reveal transaction senders and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowRevealedSenders` or weaker if you wish to allow this transaction to proceed anyway.'
|
||||
opid = self.nodes[2].z_sendmany(source, recipients, 1, 0)
|
||||
wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', revealed_senders_msg)
|
||||
|
||||
# We can't create a transaction with an unknown privacy policy.
|
||||
assert_raises_message(
|
||||
JSONRPCException,
|
||||
'Unknown privacy policy name \'ZcashIsAwesome\'',
|
||||
self.nodes[2].z_sendmany,
|
||||
source, recipients, 1, 0, 'ZcashIsAwesome')
|
||||
|
||||
# If we set any policy that does not include AllowRevealedSenders,
|
||||
# z_sendmany also fails.
|
||||
for policy in [
|
||||
'FullPrivacy',
|
||||
'AllowRevealedAmounts',
|
||||
'AllowRevealedRecipients',
|
||||
]:
|
||||
opid = self.nodes[2].z_sendmany(source, recipients, 1, 0, policy)
|
||||
wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', revealed_senders_msg)
|
||||
|
||||
# By setting the correct policy, we can create the transaction.
|
||||
opid = self.nodes[2].z_sendmany(source, recipients, 1, 0, 'AllowRevealedSenders')
|
||||
wait_and_assert_operationid_status(self.nodes[2], opid)
|
||||
|
||||
self.nodes[2].generate(1)
|
||||
|
@ -181,7 +215,32 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
|||
# Send some funds to a specific legacy taddr that we can spend from
|
||||
recipients = []
|
||||
recipients.append({"address":mytaddr, "amount":5})
|
||||
opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0)
|
||||
|
||||
# If we attempt to spend with the default privacy policy, z_sendmany
|
||||
# returns an error because it needs to create a transparent recipient in
|
||||
# a transaction involving a Unified Address.
|
||||
assert_raises_message(
|
||||
JSONRPCException,
|
||||
'AllowRevealedRecipients',
|
||||
self.nodes[0].z_sendmany,
|
||||
n0ua0, recipients, 1, 0)
|
||||
|
||||
# If we set any policy that does not include AllowRevealedRecipients,
|
||||
# z_sendmany also returns an error.
|
||||
for policy in [
|
||||
'FullPrivacy',
|
||||
'AllowRevealedAmounts',
|
||||
'AllowRevealedSenders',
|
||||
'AllowLinkingAccountAddresses',
|
||||
]:
|
||||
assert_raises_message(
|
||||
JSONRPCException,
|
||||
'AllowRevealedRecipients',
|
||||
self.nodes[0].z_sendmany,
|
||||
n0ua0, recipients, 1, 0, policy)
|
||||
|
||||
# By setting the correct policy, we can create the transaction.
|
||||
opid = self.nodes[0].z_sendmany(n0ua0, recipients, 1, 0, 'AllowRevealedRecipients')
|
||||
wait_and_assert_operationid_status(self.nodes[0], opid)
|
||||
|
||||
self.nodes[0].generate(1)
|
||||
|
@ -204,10 +263,12 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
|||
self.check_balance(0, 0, n0ua0, {'sapling': 2})
|
||||
assert_equal(Decimal(self.nodes[2].z_getbalance(myzaddr)), zbalance)
|
||||
|
||||
# Send funds back from the legacy taddr to the UA
|
||||
# Send funds back from the legacy taddr to the UA. This requires
|
||||
# AllowRevealedSenders, but we can also use any weaker policy that
|
||||
# includes it.
|
||||
recipients = []
|
||||
recipients.append({"address":n0ua0, "amount":4})
|
||||
opid = self.nodes[2].z_sendmany(mytaddr, recipients, 1, 0)
|
||||
opid = self.nodes[2].z_sendmany(mytaddr, recipients, 1, 0, 'AllowFullyTransparent')
|
||||
wait_and_assert_operationid_status(self.nodes[2], opid)
|
||||
|
||||
self.nodes[2].generate(1)
|
||||
|
@ -230,5 +291,99 @@ class WalletZSendmanyTest(BitcoinTestFramework):
|
|||
self.check_balance(0, 0, n0ua0, {'sapling': 8})
|
||||
assert_equal(Decimal(self.nodes[2].z_getbalance(myzaddr)), zbalance)
|
||||
|
||||
#
|
||||
# Test that z_sendmany avoids UA linkability unless we allow it.
|
||||
#
|
||||
|
||||
# Generate a new account with two new addresses.
|
||||
n1account = self.nodes[1].z_getnewaccount()['account']
|
||||
n1ua0 = self.nodes[1].z_getaddressforaccount(n1account)['unifiedaddress']
|
||||
n1ua1 = self.nodes[1].z_getaddressforaccount(n1account)['unifiedaddress']
|
||||
|
||||
# Send funds to the transparent receivers of both addresses.
|
||||
for ua in [n1ua0, n1ua1]:
|
||||
taddr = self.nodes[1].z_listunifiedreceivers(ua)['transparent']
|
||||
self.nodes[0].sendtoaddress(taddr, 2)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# The account should see all funds.
|
||||
assert_equal(
|
||||
self.nodes[1].z_getbalanceforaccount(n1account)['pools'],
|
||||
{'transparent': {'valueZat': 4 * COIN}},
|
||||
)
|
||||
|
||||
# The addresses should see only the transparent funds sent to them.
|
||||
assert_equal(self.nodes[1].z_getbalance(n1ua0), 2)
|
||||
assert_equal(self.nodes[1].z_getbalance(n1ua1), 2)
|
||||
|
||||
# If we try to send 3 ZEC from n1ua0, it will fail with too-few funds.
|
||||
recipients = [{"address":n0ua0, "amount":3}]
|
||||
linked_addrs_msg = 'Insufficient funds: have 2.00, need 3.00 (This transaction may require selecting transparent coins that were sent to multiple Unified Addresses, which is not enabled by default because it would create a public link between the transparent receivers of these addresses. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` parameter set to `AllowLinkingAccountAddresses` or weaker if you wish to allow this transaction to proceed anyway.)'
|
||||
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0)
|
||||
wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', linked_addrs_msg)
|
||||
|
||||
# If we try it again with any policy that is too strong, it also fails.
|
||||
for policy in [
|
||||
'FullPrivacy',
|
||||
'AllowRevealedAmounts',
|
||||
'AllowRevealedRecipients',
|
||||
'AllowRevealedSenders',
|
||||
'AllowFullyTransparent',
|
||||
]:
|
||||
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, policy)
|
||||
wait_and_assert_operationid_status(self.nodes[1], opid, 'failed', linked_addrs_msg)
|
||||
|
||||
# Once we provide a sufficiently-weak policy, the transaction succeeds.
|
||||
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'AllowLinkingAccountAddresses')
|
||||
wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# The account should see the remaining funds, and they should have been
|
||||
# sent to the Sapling change address (because NU5 is not active).
|
||||
assert_equal(
|
||||
self.nodes[1].z_getbalanceforaccount(n1account)['pools'],
|
||||
{'sapling': {'valueZat': 1 * COIN}},
|
||||
)
|
||||
|
||||
# The addresses should both show the same balance, as they both show the
|
||||
# Sapling balance.
|
||||
assert_equal(self.nodes[1].z_getbalance(n1ua0), 1)
|
||||
assert_equal(self.nodes[1].z_getbalance(n1ua1), 1)
|
||||
|
||||
#
|
||||
# Test NoPrivacy policy
|
||||
#
|
||||
|
||||
# Send some legacy transparent funds to n1ua0, creating Sapling outputs.
|
||||
recipients = [{"address":n1ua0, "amount":10}]
|
||||
# This requires the AllowRevealedSenders policy...
|
||||
opid = self.nodes[2].z_sendmany('ANY_TADDR', recipients, 1, 0)
|
||||
wait_and_assert_operationid_status(self.nodes[2], opid, 'failed', revealed_senders_msg)
|
||||
# ... which we can always override with the NoPrivacy policy.
|
||||
opid = self.nodes[2].z_sendmany('ANY_TADDR', recipients, 1, 0, 'NoPrivacy')
|
||||
wait_and_assert_operationid_status(self.nodes[2], opid)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# Send some funds from node 1's account to a transparent address.
|
||||
recipients = [{"address":mytaddr, "amount":5}]
|
||||
# This requires the AllowRevealedRecipients policy...
|
||||
assert_raises_message(
|
||||
JSONRPCException,
|
||||
'AllowRevealedRecipients',
|
||||
self.nodes[1].z_sendmany,
|
||||
n1ua0, recipients, 1, 0)
|
||||
# ... which we can always override with the NoPrivacy policy.
|
||||
opid = self.nodes[1].z_sendmany(n1ua0, recipients, 1, 0, 'NoPrivacy')
|
||||
wait_and_assert_operationid_status(self.nodes[1], opid)
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletZSendmanyTest().main()
|
||||
|
|
|
@ -123,6 +123,16 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
|||
}, recipient.address);
|
||||
}
|
||||
|
||||
if (recipientPools_.count(OutputPool::Transparent) && !strategy_.AllowRevealedRecipients()) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"This transaction would have transparent recipients, 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.");
|
||||
}
|
||||
|
||||
// Log the context info i.e. the call parameters to z_sendmany
|
||||
if (LogAcceptCategory("zrpcunsafe")) {
|
||||
LogPrint("zrpcunsafe", "%s: z_sendmany initialized (params=%s)\n", getId(), contextInfo.write());
|
||||
|
@ -247,6 +257,7 @@ uint256 AsyncRPCOperation_sendmany::main_impl() {
|
|||
FormatMoney(changeAmount),
|
||||
FormatMoney(dustThreshold)));
|
||||
} else {
|
||||
bool isFromUa = std::holds_alternative<libzcash::UnifiedAddress>(ztxoSelector_.GetPattern());
|
||||
throw JSONRPCError(
|
||||
RPC_WALLET_INSUFFICIENT_FUNDS,
|
||||
strprintf(
|
||||
|
@ -255,10 +266,27 @@ uint256 AsyncRPCOperation_sendmany::main_impl() {
|
|||
+ (allowTransparentCoinbase ? "" :
|
||||
"; note that coinbase outputs will not be selected if you specify "
|
||||
"ANY_TADDR or if any transparent recipients are included.")
|
||||
+ ((!isFromUa || strategy_.AllowLinkingAccountAddresses()) ? "" :
|
||||
" (This transaction may require selecting transparent coins that were sent "
|
||||
"to multiple Unified Addresses, which is not enabled by default because "
|
||||
"it would create a public link between the transparent receivers of these "
|
||||
"addresses. THIS MAY AFFECT YOUR PRIVACY. Resubmit with the `privacyPolicy` "
|
||||
"parameter set to `AllowLinkingAccountAddresses` or weaker if you wish to "
|
||||
"allow this transaction to proceed anyway.)")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(spendable.utxos.empty() || strategy_.AllowRevealedSenders())) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"This transaction requires selecting transparent coins, which is "
|
||||
"not enabled by default because it will publicly reveal transaction "
|
||||
"senders and amounts. THIS MAY AFFECT YOUR PRIVACY. Resubmit "
|
||||
"with the `privacyPolicy` parameter set to `AllowRevealedSenders` "
|
||||
"or weaker if you wish to allow this transaction to proceed anyway.");
|
||||
}
|
||||
|
||||
spendable.LogInputs(getId());
|
||||
|
||||
CAmount t_inputs_total{0};
|
||||
|
|
|
@ -4493,9 +4493,22 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
" One of the following strings:\n"
|
||||
" - \"FullPrivacy\": Only allow fully-shielded transactions (involving a single shielded pool).\n"
|
||||
" - \"LegacyCompat\": If the transaction involves any Unified Addressess, this is equivalent to\n"
|
||||
" \"FullPrivacy\". Otherwise, this is equivalent to \"AllowRevealedAmounts\".\n"
|
||||
" \"FullPrivacy\". Otherwise, this is equivalent to \"AllowFullyTransparent\".\n"
|
||||
" - \"AllowRevealedAmounts\": Allow funds to cross between shielded pools, revealing the amount\n"
|
||||
" that crosses pools.\n"
|
||||
" - \"AllowRevealedRecipients\": Allow transparent recipients. This also implies revealing\n"
|
||||
" information described under \"AllowRevealedAmounts\".\n"
|
||||
" - \"AllowRevealedSenders\": Allow transparent funds to be spent, revealing the sending\n"
|
||||
" addresses and amounts. This implies revealing information described under \"AllowRevealedAmounts\".\n"
|
||||
" - \"AllowFullyTransparent\": Allow transaction to both spend transparent funds and have\n"
|
||||
" transparent recipients. This implies revealing information described under \"AllowRevealedSenders\"\n"
|
||||
" and \"AllowRevealedRecipients\".\n"
|
||||
" - \"AllowLinkingAccountAddresses\": Allow selecting transparent coins from the full account,\n"
|
||||
" rather than just the funds sent to the transparent receiver in the provided Unified Address.\n"
|
||||
" This implies revealing information described under \"AllowRevealedSenders\".\n"
|
||||
" - \"NoPrivacy\": Allow the transaction to reveal any information necessary to create it.\n"
|
||||
" This implies revealing information described under \"AllowFullyTransparent\" and\n"
|
||||
" \"AllowLinkingAccountAddresses\".\n"
|
||||
"\nResult:\n"
|
||||
"\"operationid\" (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
|
||||
"\nExamples:\n"
|
||||
|
@ -4553,7 +4566,11 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
"Invalid from address: should be a taddr, zaddr, UA, or the string 'ANY_TADDR'.");
|
||||
}
|
||||
|
||||
auto ztxoSelectorOpt = pwalletMain->ZTXOSelectorForAddress(decoded.value(), true, false);
|
||||
auto ztxoSelectorOpt = pwalletMain->ZTXOSelectorForAddress(
|
||||
decoded.value(),
|
||||
true,
|
||||
// LegacyCompat does not include AllowLinkingAccountAddresses.
|
||||
maybeStrategy.has_value() ? maybeStrategy.value().AllowLinkingAccountAddresses() : false);
|
||||
if (!ztxoSelectorOpt.has_value()) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
|
@ -4669,7 +4686,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
// Default privacy policy is "LegacyCompat".
|
||||
involvesUnifiedAddress ?
|
||||
TransactionStrategy(PrivacyPolicy::FullPrivacy) :
|
||||
TransactionStrategy(PrivacyPolicy::AllowRevealedAmounts)
|
||||
TransactionStrategy(PrivacyPolicy::AllowFullyTransparent)
|
||||
);
|
||||
|
||||
// Sanity check for transaction size
|
||||
|
|
|
@ -1249,7 +1249,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
|
|||
auto selector = pwalletMain->ZTXOSelectorForAddress(zaddr1, true, false).value();
|
||||
TransactionBuilder builder(consensusParams, nHeight + 1, std::nullopt, pwalletMain);
|
||||
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, taddr1, 100*COIN, "DEADBEEF") };
|
||||
TransactionStrategy strategy;
|
||||
TransactionStrategy strategy(PrivacyPolicy::AllowRevealedRecipients);
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 1, strategy));
|
||||
operation->main();
|
||||
BOOST_CHECK(operation->isFailed());
|
||||
|
@ -1363,7 +1363,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling)
|
|||
|
||||
auto selector = pwalletMain->ZTXOSelectorForAddress(taddr, true, false).value();
|
||||
std::vector<SendManyRecipient> recipients = { SendManyRecipient(std::nullopt, pa, 1*COIN, "ABCD") };
|
||||
TransactionStrategy strategy;
|
||||
TransactionStrategy strategy(PrivacyPolicy::AllowRevealedSenders);
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(std::move(builder), selector, recipients, 0, strategy));
|
||||
std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
|
||||
|
||||
|
@ -1372,7 +1372,9 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling)
|
|||
|
||||
// Generate the Sapling shielding transaction
|
||||
operation->main();
|
||||
BOOST_CHECK(operation->isSuccess());
|
||||
if (!operation->isSuccess()) {
|
||||
BOOST_FAIL(operation->getErrorMessage());
|
||||
}
|
||||
|
||||
// Get the transaction
|
||||
auto result = operation->getResult();
|
||||
|
|
|
@ -7096,6 +7096,16 @@ std::optional<TransactionStrategy> TransactionStrategy::FromString(std::string p
|
|||
strategy.privacy = PrivacyPolicy::FullPrivacy;
|
||||
} else if (privacyPolicy == "AllowRevealedAmounts") {
|
||||
strategy.privacy = PrivacyPolicy::AllowRevealedAmounts;
|
||||
} else if (privacyPolicy == "AllowRevealedRecipients") {
|
||||
strategy.privacy = PrivacyPolicy::AllowRevealedRecipients;
|
||||
} else if (privacyPolicy == "AllowRevealedSenders") {
|
||||
strategy.privacy = PrivacyPolicy::AllowRevealedSenders;
|
||||
} else if (privacyPolicy == "AllowFullyTransparent") {
|
||||
strategy.privacy = PrivacyPolicy::AllowFullyTransparent;
|
||||
} else if (privacyPolicy == "AllowLinkingAccountAddresses") {
|
||||
strategy.privacy = PrivacyPolicy::AllowLinkingAccountAddresses;
|
||||
} else if (privacyPolicy == "NoPrivacy") {
|
||||
strategy.privacy = PrivacyPolicy::NoPrivacy;
|
||||
} else {
|
||||
// Unknown privacy policy.
|
||||
return std::nullopt;
|
||||
|
@ -7109,6 +7119,62 @@ bool TransactionStrategy::AllowRevealedAmounts() {
|
|||
case PrivacyPolicy::FullPrivacy:
|
||||
return false;
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
case PrivacyPolicy::AllowFullyTransparent:
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
case PrivacyPolicy::NoPrivacy:
|
||||
return true;
|
||||
default:
|
||||
// Fail closed.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TransactionStrategy::AllowRevealedRecipients() {
|
||||
switch (privacy) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
return false;
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
case PrivacyPolicy::AllowFullyTransparent:
|
||||
case PrivacyPolicy::NoPrivacy:
|
||||
return true;
|
||||
default:
|
||||
// Fail closed.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TransactionStrategy::AllowRevealedSenders() {
|
||||
switch (privacy) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
return false;
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
case PrivacyPolicy::AllowFullyTransparent:
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
case PrivacyPolicy::NoPrivacy:
|
||||
return true;
|
||||
default:
|
||||
// Fail closed.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TransactionStrategy::AllowLinkingAccountAddresses() {
|
||||
switch (privacy) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
case PrivacyPolicy::AllowFullyTransparent:
|
||||
return false;
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
case PrivacyPolicy::NoPrivacy:
|
||||
return true;
|
||||
default:
|
||||
// Fail closed.
|
||||
|
|
|
@ -721,6 +721,11 @@ public:
|
|||
enum class PrivacyPolicy {
|
||||
FullPrivacy,
|
||||
AllowRevealedAmounts,
|
||||
AllowRevealedRecipients,
|
||||
AllowRevealedSenders,
|
||||
AllowFullyTransparent,
|
||||
AllowLinkingAccountAddresses,
|
||||
NoPrivacy,
|
||||
};
|
||||
|
||||
class TransactionStrategy {
|
||||
|
@ -734,6 +739,9 @@ public:
|
|||
static std::optional<TransactionStrategy> FromString(std::string privacyPolicy);
|
||||
|
||||
bool AllowRevealedAmounts();
|
||||
bool AllowRevealedRecipients();
|
||||
bool AllowRevealedSenders();
|
||||
bool AllowLinkingAccountAddresses();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue