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

Implement cap 0006 #2016

Merged
merged 17 commits into from
Apr 3, 2019
Merged

Implement cap 0006 #2016

merged 17 commits into from
Apr 3, 2019

Conversation

jonjove
Copy link
Contributor

@jonjove jonjove commented Mar 21, 2019

Implementation of https://github.com/stellar/stellar-protocol/blob/master/core/cap-0006.md except that manage offer has not yet been renamed to manage sell offer.

@@ -25,6 +25,22 @@ namespace stellar

using namespace std;

static int64_t
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if those two methods should be merged into one, as getOfferBuyingLiabilities and getOfferSellingLiabilities are mostly called in pairs and it may not be 100% optimal to call exchangeV10WithoutPriceErrorThresholds twice with the same parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally agree that it's not 100% optimal because we do the same work twice. But the inefficiency is probably very minor because exchangeV10WithoutPriceErrorThresholds is just a sequence of branches and arithmetic with no database access. I think I'll leave it this way for now since it keeps the code cleaner, but if it ever shows up in profiling as a bottleneck then we can definitely change it because this is purely an implementation detail.

issuer.pay(a4, cur4, INT64_MAX);
a4.changeTrust(cur3, INT64_MAX);

a4.manageOffer(0, cur4, cur3, Price{price.d, price.n},
Copy link
Contributor

Choose a reason for hiding this comment

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

I see you are testing manageOffer/manageBuyOffer and manageOffer/manageOffer pairs.
Is there a reason to not test manageBuyOffer/manageOffer and manageBuyOffer/manageBuyOffer pairs here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is no need to test the other combinations. There is only one type of OfferEntry, so there is no distinction between the offers created by ManageOffer and ManageBuyOffer once they are in the ledger.

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.

Looks good in general, a few things missing:

  • forgot to rename ManageOfferOp -> ManageSellOfferOp
  • (missing from CAP006) we should probably rename CreatePassiveOfferOp -> CreatePassiveSellOfferOp for consistency
  • need to run clang-format on Stellar-transaction.x
  • should BaseManageOfferOpFrame be renamed ManageOfferOpFrameBase ? That way, we keep all the Manage*Offer files together

src/transactions/BaseManageOfferOpFrame.cpp Outdated Show resolved Hide resolved
src/transactions/BaseManageOfferOpFrame.cpp Outdated Show resolved Hide resolved
src/transactions/BaseManageOfferOpFrame.cpp Outdated Show resolved Hide resolved
src/transactions/BaseManageOfferOpFrame.cpp Outdated Show resolved Hide resolved
}
if (mManageBuyOffer.offerID == 0 && mManageBuyOffer.buyAmount == 0)
{
// Note: This currently does not match the return code of ManageOfferOp.
Copy link
Contributor

Choose a reason for hiding this comment

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

now that I see this, maybe we should make the change, share the code and remove the comment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, and I'll submit a PR to update the CAP accordingly.

ManageBuyOfferOpFrame::getOfferBuyingLiabilities()
{
auto res = exchangeV10WithoutPriceErrorThresholds(
mManageBuyOffer.price, INT64_MAX, INT64_MAX, INT64_MAX,
Copy link
Contributor

Choose a reason for hiding this comment

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

didn't realize that we're using this price and not the inverse (and that's what the cap says)

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 thought this would be the simplest approach because the price submitted is the price that gets recorded in the ledger. Is there some reason you would prefer the inverse?

Copy link
Contributor

Choose a reason for hiding this comment

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

More that it doesn't seem super natural to me as offers are expressed in terms of selling things, so buying implies using the semantics for the other half of the book maybe?

If I have an offer on the book:

  • sell 1000 JPY for USD at price 0.009 (manageSellOffer on the "sell JPY for USD" book)

That I try to take entirely (1 is current CAP006, 2 is using the inverse):

  1. buy 1000 JPY for USD at price 110 (manageBuyOffer on the "sell USD for JPY" book)
  2. buy 1000 JPY for USD at price 0.009 (manageBuyOffer on the "sell USD for JPY" book)

Right now we only "sell" (the only thing we can do now)
sell 9 USD for JPY at price 110 (manageSellOffer on the "sell USD for JPY" book)

Maybe it's a UI thing. I don't know.

Copy link
Contributor

Choose a reason for hiding this comment

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

@jonjove @MonsieurNicolas chipping in here.. this is what I’d expect as a consumer of these APIs:

when dealing with the XLM/USD market:
sell 100 XLM at $0.095
buy 100 XLM at $0.090

converting the same actions above to USD/XLM representation:
sell 9.5 USD at price 11.1111111
buy 9.0 USD at price 10.5263158

i.e. prices (buy and sell) should always be in the quote (counter) currency where for a market X/Y, X is the base currency and Y is the quote currency.
Also, amounts should always be specified in the base currency as in the examples above.

@@ -20,7 +20,7 @@
#include "transactions/CreateAccountOpFrame.h"
#include "transactions/InflationOpFrame.h"
#include "transactions/ManageDataOpFrame.h"
#include "transactions/ManageOfferOpFrame.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

should also apply adds/renames to the Visual Studio files

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Also added ManageBuyOfferOpFrame and ManageOfferOpFrameBase.

@graydon
Copy link
Contributor

graydon commented Apr 2, 2019

I spent a few days reviewing this and made a bunch of notes about comments I want to add / renamings for clarity but none of that is pressing, will file later as followups. Thanks to Jon for extensive conversation and clarification, I'm happy with this change (and even think I roughly understand it now!)

@MonsieurNicolas
Copy link
Contributor

r+ 85da215

latobarita added a commit that referenced this pull request Apr 3, 2019
Implement cap 0006

Reviewed-by: MonsieurNicolas
@latobarita latobarita merged commit 85da215 into stellar:master Apr 3, 2019
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.

7 participants