Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cap-0018 - Implementation after removing low-level auth checks starting from v10 #2387

Merged
merged 3 commits into from
Apr 4, 2020

Conversation

sisuresh
Copy link
Contributor

@sisuresh sisuresh commented Jan 14, 2020

Description

Implements https://github.com/stellar/stellar-protocol/blob/master/core/cap-0018.md

Checklist

  • Reviewed the contributing document
  • Rebased on top of master (no merge commits)
  • Ran clang-format v5.0.0 (via make format or the Visual Studio extension)
  • Compiles
  • Ran all tests
  • If change impacts performance, include supporting evidence per the performance document

Copy link
Contributor

@jonjove jonjove left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a much cleaner implementation, much easier to review and reason about. I left a few small comments, although I haven't reviewed the new AllowTrust tests yet.

src/transactions/AllowTrustOpFrame.cpp Outdated Show resolved Hide resolved
src/invariant/InvariantUtils.cpp Outdated Show resolved Hide resolved
src/invariant/LedgerEntryIsValid.cpp Outdated Show resolved Hide resolved
@@ -50,7 +50,7 @@ canSellAtMost(LedgerTxnHeader const& header, LedgerTxnEntry const& account,
return std::max({getAvailableBalance(header, account), int64_t(0)});
}

if (trustLine && trustLine.isAuthorized())
if (trustLine && trustLine.isAuthorizedToMaintainLiabilities())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need to check authorization here at all starting from version 10? Same thing for the other overload.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point. We don't need to check as the authorization is checked prior to this for v10 and up. I did this because it looked cleaner than header.current().ledgerVersion >= 10 || trustLine.isAuthorized(), but I think the intention is clearer if we only check the authorization pre v10. I'll make the change.

Copy link
Contributor

@MonsieurNicolas MonsieurNicolas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a few minor questions. not sure if you guys discussed defensive coding practices

src/invariant/LiabilitiesMatchOffers.cpp Outdated Show resolved Hide resolved
src/transactions/OfferExchange.cpp Outdated Show resolved Hide resolved
src/transactions/TransactionUtils.cpp Outdated Show resolved Hide resolved
src/transactions/TransactionUtils.cpp Outdated Show resolved Hide resolved
src/transactions/TransactionUtils.cpp Show resolved Hide resolved
@MonsieurNicolas MonsieurNicolas mentioned this pull request Mar 17, 2020
6 tasks
@sisuresh sisuresh force-pushed the removeLowLevelAuthChecks branch from 4c10221 to ead4492 Compare March 18, 2020 01:17
src/util/ValidityUtils.cpp Outdated Show resolved Hide resolved
src/transactions/TransactionUtils.cpp Outdated Show resolved Hide resolved
@sisuresh sisuresh force-pushed the removeLowLevelAuthChecks branch from ead4492 to 16d6d5a Compare March 19, 2020 20:06
@sisuresh sisuresh force-pushed the removeLowLevelAuthChecks branch from 16d6d5a to 902b5bc Compare March 26, 2020 22:35
@sisuresh sisuresh force-pushed the removeLowLevelAuthChecks branch from 902b5bc to 6ffe2ed Compare April 1, 2020 03:34
Copy link
Contributor

@jonjove jonjove left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. I left a few very minor comments on one of the tests. But I also had some thoughts while reviewing the PR that aren't necessarily specific to any single line:

  • I'm not sure that the defensive programming approach that we took in this PR is the right one. I am of the opinion that, starting from protocol 10 (or maybe 13) we should throw if we reach addBalance, addBuyingLiabilities, etc with !isAuthorizedToMaintainLiabilities. I think this is the correct approach because we are already depending on the client code to check that it is correct between isAuthorizedToMaintainLiabilities and isAuthorized. If the client code has permitted those functions to be reached in the case mentioned above, then there is definitely a logic error. We shouldn't carry on processing the transaction if there is definitely a logic error, instead we should return txINTERNAL_ERROR.
  • We added defensive programming checks to getMaxAmountReceive but they are missing from the analogous function getAvailableBalance (which didn't require any changes in this PR).
  • The changes in the first commit were based off of the assumption that we always check authorization before reaching those functions, but that isn't true on the path through releaseLiabilities (see, for example, ManageOfferOpFrameBase.cpp:224 and note that the offer loaded there does not necessarily have the same assets as specified in the operation). Now assuming that everything works correctly, this shouldn't cause any issues because an offer in the ledger should have authorized trust lines. But we took similar precautions at OfferExchange.cpp:1112.

src/transactions/test/PathPaymentTests.cpp Outdated Show resolved Hide resolved
src/transactions/test/OfferTests.cpp Outdated Show resolved Hide resolved
src/transactions/test/OfferTests.cpp Outdated Show resolved Hide resolved
src/transactions/test/OfferTests.cpp Show resolved Hide resolved
@sisuresh sisuresh force-pushed the removeLowLevelAuthChecks branch 2 times, most recently from cade8ee to 89fe97f Compare April 2, 2020 01:29
@sisuresh
Copy link
Contributor Author

sisuresh commented Apr 2, 2020

@jonjove

This looks good. I left a few very minor comments on one of the tests. But I also had some thoughts while reviewing the PR that aren't necessarily specific to any single line:

  • I'm not sure that the defensive programming approach that we took in this PR is the right one. I am of the opinion that, starting from protocol 10 (or maybe 13) we should throw if we reach addBalance, addBuyingLiabilities, etc with !isAuthorizedToMaintainLiabilities. I think this is the correct approach because we are already depending on the client code to check that it is correct between isAuthorizedToMaintainLiabilities and isAuthorized. If the client code has permitted those functions to be reached in the case mentioned above, then there is definitely a logic error. We shouldn't carry on processing the transaction if there is definitely a logic error, instead we should return txINTERNAL_ERROR.

I added a commit that throws if we reach those methods starting in protocol 10. I like this approach as the assumptions made are clear and enforced.

  • We added defensive programming checks to getMaxAmountReceive but they are missing from the analogous function getAvailableBalance (which didn't require any changes in this PR).

I added an authorization check in getAvailableBalance. This isn't necessary, but I think it makes sense because there's no reason to retrieve the balance of an unauthorized asset (since nothing can be done with that asset).

  • The changes in the first commit were based off of the assumption that we always check authorization before reaching those functions, but that isn't true on the path through releaseLiabilities (see, for example, ManageOfferOpFrameBase.cpp:224 and note that the offer loaded there does not necessarily have the same assets as specified in the operation). Now assuming that everything works correctly, this shouldn't cause any issues because an offer in the ledger should have authorized trust lines. But we took similar precautions at OfferExchange.cpp:1112.

This is an interesting scenario. The authorization shouldn't matter since releaseLiabilities is removing offers. However, if there are unauthorized offers in the ledger, we will throw in addBuyingLiabilities and addSellingLiabilities (with my latest change). Because of the new invariants, I think the check at OfferExchange.cpp:1112 is unnecessary because releaseLiabilities is called on the existing offer at OfferExchange.cpp:1100, which will do the auth check anyways. If you agree, I will remove the check on OfferExchange.cpp:1112.

Copy link
Contributor

@jonjove jonjove left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting scenario. The authorization shouldn't matter since releaseLiabilities is removing offers. However, if there are unauthorized offers in the ledger, we will throw in addBuyingLiabilities and addSellingLiabilities (with my latest change). Because of the new invariants, I think the check at OfferExchange.cpp:1112 is unnecessary because releaseLiabilities is called on the existing offer at OfferExchange.cpp:1100, which will do the auth check anyways. If you agree, I will remove the check on OfferExchange.cpp:1112.

Yes, I agree that the check on OfferExchange.cpp:1112 is unnecessary now. I think it would be worth adding a comment where releaseLiabilitites is used on OfferExchange.cpp:1099 indicating that this is being checked there. Have you checked that everything makes sense at other places where releaseLiabilities is used, such as AllowTrustOpFrame.cpp:135 (there are a few other places too)?

@@ -429,14 +448,18 @@ getAvailableBalance(LedgerTxnHeader const& header, LedgerEntry const& le)
}
else if (le.data.type() == TRUSTLINE)
{
if (ledgerVersionMinV10 && !isAuthorizedToMaintainLiabilities(le))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to use checkAuthorization here? I know you don't need the return value (so a comment about that would be warranted) but it looks like it would cover the throw part correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just thought it was easier to read this way. But using checkAuthorization will work as well, and will allow us to keep the throw logic in one spot. I'll make the change.

@sisuresh sisuresh force-pushed the removeLowLevelAuthChecks branch from 89fe97f to 8d6f542 Compare April 2, 2020 16:02
@sisuresh
Copy link
Contributor Author

sisuresh commented Apr 2, 2020

This is an interesting scenario. The authorization shouldn't matter since releaseLiabilities is removing offers. However, if there are unauthorized offers in the ledger, we will throw in addBuyingLiabilities and addSellingLiabilities (with my latest change). Because of the new invariants, I think the check at OfferExchange.cpp:1112 is unnecessary because releaseLiabilities is called on the existing offer at OfferExchange.cpp:1100, which will do the auth check anyways. If you agree, I will remove the check on OfferExchange.cpp:1112.

Yes, I agree that the check on OfferExchange.cpp:1112 is unnecessary now. I think it would be worth adding a comment where releaseLiabilitites is used on OfferExchange.cpp:1099 indicating that this is being checked there. Have you checked that everything makes sense at other places where releaseLiabilities is used, such as AllowTrustOpFrame.cpp:135 (there are a few other places too)?

Yeah the other releaseLiabilities calls look good. Related to this - Do you think it makes sense to throw if unauthorized liabilities are being released? Obviously the scenario shouldn't happen, but if it was encountered for some reason, you could make the argument that the offers should still be pulled (and log an error).

@sisuresh sisuresh force-pushed the removeLowLevelAuthChecks branch from 8d6f542 to 1ca2deb Compare April 3, 2020 19:08
@MonsieurNicolas
Copy link
Contributor

r+ 1ca2deb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants