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

Ripd1373 #2015

Closed
wants to merge 8 commits into from
Closed

Ripd1373 #2015

wants to merge 8 commits into from

Conversation

seelabs
Copy link
Collaborator

@seelabs seelabs commented Feb 13, 2017

New rules for payment paths:

  • Sanity check on newly created strands
  • Better loop detection
  • Better tests (test every combination of path element pairs)
  • Disallow any root issuer (even for xrp)
  • Disallow compount element typs in path
  • Issue was not reset when currency was XRP
  • Add amendment

@seelabs
Copy link
Collaborator Author

seelabs commented Feb 13, 2017

The "Fix limiting step re-execute bug" does not need to be reviewed, it's a separate PR.

Copy link
Collaborator

@scottschurr scottschurr left a comment

Choose a reason for hiding this comment

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

I found a very few nits, most of which you can take or leave. Looks very nice for the most part.

There is one change, however, that makes the embedded programmer lurking under my skin squirm. When you turn all of those unit tests into variadic templates just so you can pass in a variable number of features you're making the code generator work overtime. And all of the features are the same type! I hope we don't need to take up that much address space with almost identical unit tests.

Perhaps the same goal could be accomplished by passing in a vector<uint256> or something similar? Please consider that. Thanks.

!isConsistent(deliver) || (sendMaxIssue && !isConsistent(*sendMaxIssue)))
return {temBAD_PATH, Strand{}};

for (auto const& p : path)
Copy link
Collaborator

Choose a reason for hiding this comment

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

The tiniest of nits: an STPath consists of ordered STPathElements? To me p is not evocative of STPathElement. Perhaps e or elem?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

{
auto const t = p.getNodeType();

if (t > STPathElement::Type::typeAll || !t)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just a thought, would you get a better check if you replace t > STPathElement::Type::typeAll with (t & ~STPathElement::Type::typeAll) != 0?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

return pe.getNodeType () & STPathElement::typeCurrency;
};

std::vector<STPathElement> normPath;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I vaguely recall there's an upper limit on Path length (although I'm not seeing evidence of that here)? If there is an upper limit you could replace this std::vector with a boost::container::static_vector and avoid a trip to the heap. But you'd also have to add a check that path.size() was in range. Just a thought.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That limit lives in Payment.h and is checked in the payment tx preclaim. I could do this in two ways:

  1. Make that limit public and add a dependency between PaySteps.cpp and Payment.h. I don't like dependencies between lower-level routines and higher level.

  2. I could set a largish limit - say 32 - and a comment that if the number of path steps are increased, that should be increased as well. That seems fragile.

While I love getting rid of memory allocations, I don't think it's a huge deal in this case. It's done once at the start of the payment. I'd probably keep it as-is.


Issue curIssue = [&]
{
auto& currency =
Copy link
Collaborator

Choose a reason for hiding this comment

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

auto const&?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

normPath.emplace_back(sendMaxIssue->account, boost::none, boost::none);
}

for (auto& i : path)
Copy link
Collaborator

Choose a reason for hiding this comment

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

auto const&?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

if (accts.first != curAccount)
return false;

if (auto b = s->bookStepBook())
Copy link
Collaborator

Choose a reason for hiding this comment

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

auto const?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

@@ -94,6 +96,7 @@ struct BookDirs_test : public beast::unit_test::suite
void run() override
{
test_bookdir();
test_bookdir(featureFlow, featureToStrandV2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This one doesn't need test_bookdir(featureFlow)? If not it might be a good idea to include a comment why.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For certain simpler tests, I only wanted to test the pre-flow version and the latest version of flow. It wasn't necessary to test every combination of amendments and switches.

testReserve(fs...);
};
testAll();
testAll(featureFlow, featureToStrandV2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This one doesn't need test_bookdir(featureFlow)? If not it might be a good idea to include a comment why.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Same reason as above. I only needed to test the pre-flow and the latest flow.

@@ -153,6 +155,7 @@ class GatewayBalances_test : public beast::unit_test::suite
run() override
{
testGWB();
testGWB(featureFlow, featureToStrandV2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This one doesn't need test_bookdir(featureFlow)? If not it might be a good idea to include a comment why.

testDefaultRipple();

auto withFeatsTests = [this](auto&&... fs) {
testNegativeBalance();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe these three calls are missing the (fs...), so they perform exactly the same tests three times.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yep, good eye. Fixed.

@seelabs
Copy link
Collaborator Author

seelabs commented Feb 15, 2017

@scottschurr I added two commits to address your comments. The first contains the misc fixes you suggested. The second replaces uses of variadic templates with std::initializer_list to address your concerns about link size.

Copy link
Collaborator

@scottschurr scottschurr left a comment

Choose a reason for hiding this comment

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

Changes look good. I noticed one place where a bit test may have accidentally been omitted, but I'll leave that to your judgment. So I'm giving this a preemptive 👍


if (t > STPathElement::Type::typeAll || !t)
if (t & ~STPathElement::Type::typeAll)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Previously there was a check here for t having no bits set. That check seemed useful and is not covered by the new check. Was the no-bits check lost intentionally?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

@scottschurr
Copy link
Collaborator

Visual Studio can't handle the C++14 constexpr expressions in PayStrand_test.cpp.

{
auto const t = pe.getNodeType();

if ((t & ~STPathElement::Type::typeAll) || !t)
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for the Type:: since Type isn't an enum class. Feel free to change that to make it one, but then I'd ditch the type prefix.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

ownerPaysTransferFee, seenDirectIssues, seenBookOuts, j};
};

for (int i = 0; i < normPath.size () - 1; ++i)
Copy link
Contributor

Choose a reason for hiding this comment

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

So, at first I was going to say use std::size_t to avoid type-conversion warnings. And I think you should do that, but then I got to thinking: what guarantees do we have about normPath.size()?

Certainly it can't be zero - it has to be at least one. This means that using std::size_t is safe. But is it guaranteed to be at least 2? It better be, because we access the i+1 path element inside this loop.

Copy link
Collaborator Author

@seelabs seelabs Mar 17, 2017

Choose a reason for hiding this comment

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

fixed size_t issue.

Note: If size were one, we'd still be OK (the loop would not run at all). If size were zero, we'd have a bug, as the size()-1 would wrap around.

@@ -103,12 +105,12 @@ class CrossingLimits_test : public beast::unit_test::suite
balance("carol", USD(150)),
balance("bob", USD(0)), owners ("bob", 1)));
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Micronit: whitespace

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

@seelabs
Copy link
Collaborator Author

seelabs commented Mar 17, 2017

Pushed commit to address latest round of feedback

@scottschurr
Copy link
Collaborator

Latest changes look good to me. Still 👍 assuming conflicts are resolved.

Copy link
Contributor

@nbougalis nbougalis left a comment

Choose a reason for hiding this comment

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

👍 pending rebasing

@nbougalis nbougalis added the Passed Passed code review & PR owner thinks it's ready to merge. Perf sign-off may still be required. label Mar 17, 2017
* Sanity check on newly created strands
* Better loop detection
* Better tests (test every combination of path element pairs)
* Disallow any root issuer (even for xrp)
* Disallow compount element typs in path
* Issue was not reset when currency was XRP
* Add amendment
@seelabs
Copy link
Collaborator Author

seelabs commented Mar 20, 2017

rebased onto 0.60.0 Will squash after ci runs

last };

std::uint16_t state_ = 0;
static_assert(static_cast<size_t>(SB::last) <= sizeof(state_) * 8, "");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Appveyor suggests Visual Studio can't handle this static_assert. This might work for all our compilers...

static_assert (static_cast<size_t>(SB::last) <= sizeof(decltype (state_)) * 8, "");

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks. I pushed a commit with the suggested fix.

@codecov-io
Copy link

Codecov Report

Merging #2015 into develop will decrease coverage by 0.05%.
The diff coverage is 75.95%.

@@             Coverage Diff             @@
##           develop    #2015      +/-   ##
===========================================
- Coverage     67.7%   67.64%   -0.06%     
===========================================
  Files          680      680              
  Lines        49219    49399     +180     
===========================================
+ Hits         33323    33416      +93     
- Misses       15896    15983      +87
Impacted Files Coverage Δ
src/ripple/app/main/Amendments.cpp 100% <ø> (ø) ⬆️
src/ripple/app/paths/impl/XRPEndpointStep.cpp 71.87% <100%> (-4.22%) ⬇️
src/ripple/app/paths/impl/Steps.h 82.97% <100%> (+5.2%) ⬆️
src/ripple/protocol/impl/Feature.cpp 100% <100%> (ø) ⬆️
src/ripple/protocol/STPathSet.h 98.36% <100%> (ø) ⬆️
src/ripple/app/paths/impl/DirectStep.cpp 71.18% <100%> (-8.34%) ⬇️
src/ripple/app/paths/impl/BookStep.cpp 79.79% <50%> (-5.97%) ⬇️
src/ripple/app/paths/impl/PaySteps.cpp 71.84% <75%> (ø) ⬆️
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0df1b09...591eb70. Read the comment docs.

@scottschurr scottschurr mentioned this pull request Mar 21, 2017
@scottschurr
Copy link
Collaborator

Squashed and merged to develop as 846723d

@seelabs seelabs deleted the ripd1373 branch July 13, 2017 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Passed Passed code review & PR owner thinks it's ready to merge. Perf sign-off may still be required. Tx Change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants