Merge pull request #6242 from sellout/transaction-strategy
Add operations to TransactionStrategy
This commit is contained in:
commit
4bc92bf7cb
|
@ -7715,23 +7715,82 @@ std::optional<libzcash::UnifiedAddress> UnifiedAddressForReceiver::operator()(co
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
PrivacyPolicy PrivacyPolicyMeet(PrivacyPolicy a, PrivacyPolicy b)
|
||||
{
|
||||
switch (a) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
return b;
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
switch (b) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
return a;
|
||||
default: return b;
|
||||
};
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
switch (b) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
return a;
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
return PrivacyPolicy::AllowFullyTransparent;
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
return PrivacyPolicy::NoPrivacy;
|
||||
default: return b;
|
||||
};
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
switch (b) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
return a;
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
return PrivacyPolicy::AllowFullyTransparent;
|
||||
default: return b;
|
||||
};
|
||||
case PrivacyPolicy::AllowFullyTransparent:
|
||||
switch (b) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
return a;
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
return PrivacyPolicy::NoPrivacy;
|
||||
default: return b;
|
||||
};
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
switch (b) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
return a;
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
case PrivacyPolicy::AllowFullyTransparent:
|
||||
return PrivacyPolicy::NoPrivacy;
|
||||
default: return b;
|
||||
};
|
||||
case PrivacyPolicy::NoPrivacy:
|
||||
return a;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<TransactionStrategy> TransactionStrategy::FromString(std::string privacyPolicy) {
|
||||
TransactionStrategy strategy;
|
||||
|
||||
if (privacyPolicy == "FullPrivacy") {
|
||||
strategy.privacy = PrivacyPolicy::FullPrivacy;
|
||||
strategy.requestedLevel = PrivacyPolicy::FullPrivacy;
|
||||
} else if (privacyPolicy == "AllowRevealedAmounts") {
|
||||
strategy.privacy = PrivacyPolicy::AllowRevealedAmounts;
|
||||
strategy.requestedLevel = PrivacyPolicy::AllowRevealedAmounts;
|
||||
} else if (privacyPolicy == "AllowRevealedRecipients") {
|
||||
strategy.privacy = PrivacyPolicy::AllowRevealedRecipients;
|
||||
strategy.requestedLevel = PrivacyPolicy::AllowRevealedRecipients;
|
||||
} else if (privacyPolicy == "AllowRevealedSenders") {
|
||||
strategy.privacy = PrivacyPolicy::AllowRevealedSenders;
|
||||
strategy.requestedLevel = PrivacyPolicy::AllowRevealedSenders;
|
||||
} else if (privacyPolicy == "AllowFullyTransparent") {
|
||||
strategy.privacy = PrivacyPolicy::AllowFullyTransparent;
|
||||
strategy.requestedLevel = PrivacyPolicy::AllowFullyTransparent;
|
||||
} else if (privacyPolicy == "AllowLinkingAccountAddresses") {
|
||||
strategy.privacy = PrivacyPolicy::AllowLinkingAccountAddresses;
|
||||
strategy.requestedLevel = PrivacyPolicy::AllowLinkingAccountAddresses;
|
||||
} else if (privacyPolicy == "NoPrivacy") {
|
||||
strategy.privacy = PrivacyPolicy::NoPrivacy;
|
||||
strategy.requestedLevel = PrivacyPolicy::NoPrivacy;
|
||||
} else {
|
||||
// Unknown privacy policy.
|
||||
return std::nullopt;
|
||||
|
@ -7740,72 +7799,49 @@ std::optional<TransactionStrategy> TransactionStrategy::FromString(std::string p
|
|||
return strategy;
|
||||
}
|
||||
|
||||
bool TransactionStrategy::AllowRevealedAmounts() {
|
||||
switch (privacy) {
|
||||
std::string TransactionStrategy::ToString(PrivacyPolicy policy) {
|
||||
switch (policy) {
|
||||
case PrivacyPolicy::FullPrivacy:
|
||||
return false;
|
||||
return "FullPrivacy";
|
||||
case PrivacyPolicy::AllowRevealedAmounts:
|
||||
return "AllowRevealedAmounts";
|
||||
case PrivacyPolicy::AllowRevealedRecipients:
|
||||
return "AllowRevealedRecipients";
|
||||
case PrivacyPolicy::AllowRevealedSenders:
|
||||
return "AllowRevealedSenders";
|
||||
case PrivacyPolicy::AllowFullyTransparent:
|
||||
return "AllowFullyTransparent";
|
||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||
return "AllowLinkingAccountAddresses";
|
||||
case PrivacyPolicy::NoPrivacy:
|
||||
return true;
|
||||
return "NoPrivacy";
|
||||
default:
|
||||
// Fail closed.
|
||||
return false;
|
||||
assert(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::AllowRevealedAmounts() const {
|
||||
return IsCompatibleWith(PrivacyPolicy::AllowRevealedAmounts);
|
||||
}
|
||||
|
||||
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::AllowRevealedRecipients() const {
|
||||
return IsCompatibleWith(PrivacyPolicy::AllowRevealedRecipients);
|
||||
}
|
||||
|
||||
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.
|
||||
return false;
|
||||
}
|
||||
bool TransactionStrategy::AllowRevealedSenders() const {
|
||||
return IsCompatibleWith(PrivacyPolicy::AllowRevealedSenders);
|
||||
}
|
||||
|
||||
bool TransactionStrategy::AllowFullyTransparent() const {
|
||||
return IsCompatibleWith(PrivacyPolicy::AllowFullyTransparent);
|
||||
}
|
||||
|
||||
bool TransactionStrategy::AllowLinkingAccountAddresses() const {
|
||||
return IsCompatibleWith(PrivacyPolicy::AllowLinkingAccountAddresses);
|
||||
}
|
||||
|
||||
bool TransactionStrategy::IsCompatibleWith(PrivacyPolicy policy) const {
|
||||
return requestedLevel == PrivacyPolicyMeet(requestedLevel, policy);
|
||||
}
|
||||
|
||||
bool ZTXOSelector::SelectsTransparent() const {
|
||||
|
|
|
@ -759,6 +759,9 @@ public:
|
|||
|
||||
/**
|
||||
* A strategy to use for managing privacy when constructing a transaction.
|
||||
*
|
||||
* **NB**: These are intentionally in an order where `<` will never do the right
|
||||
* thing. See `PrivacyPolicyMeet` for a correct comparison.
|
||||
*/
|
||||
enum class PrivacyPolicy {
|
||||
FullPrivacy,
|
||||
|
@ -770,20 +773,54 @@ enum class PrivacyPolicy {
|
|||
NoPrivacy,
|
||||
};
|
||||
|
||||
/**
|
||||
* Privacy policies form a lattice where the relation is “strictness”. I.e.,
|
||||
* `x ≤ y` means “Policy `x` allows at least everything that policy `y` allows.”
|
||||
*
|
||||
* This function returns the meet (greatest lower bound) of `a` and `b`, i.e.
|
||||
* the strictest policy that allows everything allowed by `a` and also
|
||||
* everything allowed by `b`.
|
||||
*
|
||||
* See #6240 for the graph that this models.
|
||||
*/
|
||||
PrivacyPolicy PrivacyPolicyMeet(PrivacyPolicy a, PrivacyPolicy b);
|
||||
|
||||
class TransactionStrategy {
|
||||
PrivacyPolicy privacy;
|
||||
PrivacyPolicy requestedLevel;
|
||||
|
||||
public:
|
||||
TransactionStrategy() : privacy(PrivacyPolicy::FullPrivacy) {}
|
||||
TransactionStrategy(const TransactionStrategy& strategy) : privacy(strategy.privacy) {}
|
||||
TransactionStrategy(PrivacyPolicy privacyPolicy) : privacy(privacyPolicy) {}
|
||||
TransactionStrategy() : requestedLevel(PrivacyPolicy::FullPrivacy) {}
|
||||
TransactionStrategy(const TransactionStrategy& strategy) : requestedLevel(strategy.requestedLevel) {}
|
||||
TransactionStrategy(PrivacyPolicy privacyPolicy) : requestedLevel(privacyPolicy) {}
|
||||
|
||||
static std::optional<TransactionStrategy> FromString(std::string privacyPolicy);
|
||||
static std::string ToString(PrivacyPolicy policy);
|
||||
|
||||
bool AllowRevealedAmounts();
|
||||
bool AllowRevealedRecipients();
|
||||
bool AllowRevealedSenders();
|
||||
bool AllowLinkingAccountAddresses();
|
||||
std::string PolicyName() const {
|
||||
return ToString(requestedLevel);
|
||||
}
|
||||
|
||||
bool AllowRevealedAmounts() const;
|
||||
bool AllowRevealedRecipients() const;
|
||||
bool AllowRevealedSenders() const;
|
||||
bool AllowFullyTransparent() const;
|
||||
bool AllowLinkingAccountAddresses() const;
|
||||
|
||||
/**
|
||||
* This strategy is compatible with a given policy if it is identical to or
|
||||
* less strict than the policy.
|
||||
*
|
||||
* For example, if a transaction requires a policy no stricter than
|
||||
* `AllowRevealedSenders`, then that transaction can safely be constructed
|
||||
* if the user specifies `AllowLinkingAccountAddresses`, because
|
||||
* `AllowLinkingAccountAddresses` is compatible with `AllowRevealedSenders`
|
||||
* (the transaction will not link addresses anyway). However, if the
|
||||
* transaction required `AllowRevealedRecipients`, it could not be
|
||||
* constructed, because `AllowLinkingAccountAddresses` is _not_ compatible
|
||||
* with `AllowRevealedRecipients` (the transaction reveals recipients, which
|
||||
* is not allowed by `AllowLinkingAccountAddresses`.
|
||||
*/
|
||||
bool IsCompatibleWith(PrivacyPolicy policy) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue