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;
|
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) {
|
std::optional<TransactionStrategy> TransactionStrategy::FromString(std::string privacyPolicy) {
|
||||||
TransactionStrategy strategy;
|
TransactionStrategy strategy;
|
||||||
|
|
||||||
if (privacyPolicy == "FullPrivacy") {
|
if (privacyPolicy == "FullPrivacy") {
|
||||||
strategy.privacy = PrivacyPolicy::FullPrivacy;
|
strategy.requestedLevel = PrivacyPolicy::FullPrivacy;
|
||||||
} else if (privacyPolicy == "AllowRevealedAmounts") {
|
} else if (privacyPolicy == "AllowRevealedAmounts") {
|
||||||
strategy.privacy = PrivacyPolicy::AllowRevealedAmounts;
|
strategy.requestedLevel = PrivacyPolicy::AllowRevealedAmounts;
|
||||||
} else if (privacyPolicy == "AllowRevealedRecipients") {
|
} else if (privacyPolicy == "AllowRevealedRecipients") {
|
||||||
strategy.privacy = PrivacyPolicy::AllowRevealedRecipients;
|
strategy.requestedLevel = PrivacyPolicy::AllowRevealedRecipients;
|
||||||
} else if (privacyPolicy == "AllowRevealedSenders") {
|
} else if (privacyPolicy == "AllowRevealedSenders") {
|
||||||
strategy.privacy = PrivacyPolicy::AllowRevealedSenders;
|
strategy.requestedLevel = PrivacyPolicy::AllowRevealedSenders;
|
||||||
} else if (privacyPolicy == "AllowFullyTransparent") {
|
} else if (privacyPolicy == "AllowFullyTransparent") {
|
||||||
strategy.privacy = PrivacyPolicy::AllowFullyTransparent;
|
strategy.requestedLevel = PrivacyPolicy::AllowFullyTransparent;
|
||||||
} else if (privacyPolicy == "AllowLinkingAccountAddresses") {
|
} else if (privacyPolicy == "AllowLinkingAccountAddresses") {
|
||||||
strategy.privacy = PrivacyPolicy::AllowLinkingAccountAddresses;
|
strategy.requestedLevel = PrivacyPolicy::AllowLinkingAccountAddresses;
|
||||||
} else if (privacyPolicy == "NoPrivacy") {
|
} else if (privacyPolicy == "NoPrivacy") {
|
||||||
strategy.privacy = PrivacyPolicy::NoPrivacy;
|
strategy.requestedLevel = PrivacyPolicy::NoPrivacy;
|
||||||
} else {
|
} else {
|
||||||
// Unknown privacy policy.
|
// Unknown privacy policy.
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -7740,72 +7799,49 @@ std::optional<TransactionStrategy> TransactionStrategy::FromString(std::string p
|
||||||
return strategy;
|
return strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TransactionStrategy::AllowRevealedAmounts() {
|
std::string TransactionStrategy::ToString(PrivacyPolicy policy) {
|
||||||
switch (privacy) {
|
switch (policy) {
|
||||||
case PrivacyPolicy::FullPrivacy:
|
case PrivacyPolicy::FullPrivacy:
|
||||||
return false;
|
return "FullPrivacy";
|
||||||
case PrivacyPolicy::AllowRevealedAmounts:
|
case PrivacyPolicy::AllowRevealedAmounts:
|
||||||
|
return "AllowRevealedAmounts";
|
||||||
case PrivacyPolicy::AllowRevealedRecipients:
|
case PrivacyPolicy::AllowRevealedRecipients:
|
||||||
|
return "AllowRevealedRecipients";
|
||||||
case PrivacyPolicy::AllowRevealedSenders:
|
case PrivacyPolicy::AllowRevealedSenders:
|
||||||
|
return "AllowRevealedSenders";
|
||||||
case PrivacyPolicy::AllowFullyTransparent:
|
case PrivacyPolicy::AllowFullyTransparent:
|
||||||
|
return "AllowFullyTransparent";
|
||||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
||||||
|
return "AllowLinkingAccountAddresses";
|
||||||
case PrivacyPolicy::NoPrivacy:
|
case PrivacyPolicy::NoPrivacy:
|
||||||
return true;
|
return "NoPrivacy";
|
||||||
default:
|
default:
|
||||||
// Fail closed.
|
assert(false);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TransactionStrategy::AllowRevealedRecipients() {
|
bool TransactionStrategy::AllowRevealedAmounts() const {
|
||||||
switch (privacy) {
|
return IsCompatibleWith(PrivacyPolicy::AllowRevealedAmounts);
|
||||||
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() {
|
bool TransactionStrategy::AllowRevealedRecipients() const {
|
||||||
switch (privacy) {
|
return IsCompatibleWith(PrivacyPolicy::AllowRevealedRecipients);
|
||||||
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() {
|
bool TransactionStrategy::AllowRevealedSenders() const {
|
||||||
switch (privacy) {
|
return IsCompatibleWith(PrivacyPolicy::AllowRevealedSenders);
|
||||||
case PrivacyPolicy::FullPrivacy:
|
}
|
||||||
case PrivacyPolicy::AllowRevealedAmounts:
|
|
||||||
case PrivacyPolicy::AllowRevealedRecipients:
|
bool TransactionStrategy::AllowFullyTransparent() const {
|
||||||
case PrivacyPolicy::AllowRevealedSenders:
|
return IsCompatibleWith(PrivacyPolicy::AllowFullyTransparent);
|
||||||
case PrivacyPolicy::AllowFullyTransparent:
|
}
|
||||||
return false;
|
|
||||||
case PrivacyPolicy::AllowLinkingAccountAddresses:
|
bool TransactionStrategy::AllowLinkingAccountAddresses() const {
|
||||||
case PrivacyPolicy::NoPrivacy:
|
return IsCompatibleWith(PrivacyPolicy::AllowLinkingAccountAddresses);
|
||||||
return true;
|
}
|
||||||
default:
|
|
||||||
// Fail closed.
|
bool TransactionStrategy::IsCompatibleWith(PrivacyPolicy policy) const {
|
||||||
return false;
|
return requestedLevel == PrivacyPolicyMeet(requestedLevel, policy);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZTXOSelector::SelectsTransparent() const {
|
bool ZTXOSelector::SelectsTransparent() const {
|
||||||
|
|
|
@ -759,6 +759,9 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strategy to use for managing privacy when constructing a transaction.
|
* 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 {
|
enum class PrivacyPolicy {
|
||||||
FullPrivacy,
|
FullPrivacy,
|
||||||
|
@ -770,20 +773,54 @@ enum class PrivacyPolicy {
|
||||||
NoPrivacy,
|
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 {
|
class TransactionStrategy {
|
||||||
PrivacyPolicy privacy;
|
PrivacyPolicy requestedLevel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionStrategy() : privacy(PrivacyPolicy::FullPrivacy) {}
|
TransactionStrategy() : requestedLevel(PrivacyPolicy::FullPrivacy) {}
|
||||||
TransactionStrategy(const TransactionStrategy& strategy) : privacy(strategy.privacy) {}
|
TransactionStrategy(const TransactionStrategy& strategy) : requestedLevel(strategy.requestedLevel) {}
|
||||||
TransactionStrategy(PrivacyPolicy privacyPolicy) : privacy(privacyPolicy) {}
|
TransactionStrategy(PrivacyPolicy privacyPolicy) : requestedLevel(privacyPolicy) {}
|
||||||
|
|
||||||
static std::optional<TransactionStrategy> FromString(std::string privacyPolicy);
|
static std::optional<TransactionStrategy> FromString(std::string privacyPolicy);
|
||||||
|
static std::string ToString(PrivacyPolicy policy);
|
||||||
|
|
||||||
bool AllowRevealedAmounts();
|
std::string PolicyName() const {
|
||||||
bool AllowRevealedRecipients();
|
return ToString(requestedLevel);
|
||||||
bool AllowRevealedSenders();
|
}
|
||||||
bool AllowLinkingAccountAddresses();
|
|
||||||
|
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