-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Improve STVector256 deserialization #4204
Conversation
src/ripple/basics/Slice.h
Outdated
@@ -48,6 +48,7 @@ class Slice | |||
std::size_t size_ = 0; | |||
|
|||
public: | |||
using value_type = std::uint8_t; | |||
using const_iterator = std::uint8_t const*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe using const_iterator = value_type const*;
if (slice.size() % uint256::size() != 0) | ||
Throw<std::runtime_error>( | ||
"Bad serialization for STVector256: " + | ||
std::to_string(slice.size())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The NFTokenCancelOffer
uses a STVector256
field. The old code may have accepted an incorrectly serialized sfNFTTokenOffers
field where as the new code throws - which would make this transaction breaking. I'd be surprised if an incorrectly serialized transaction could ever make into the ledger, but I'm not sure I can prove it (code like this would assert in debug mode: https://github.com/nbougalis/rippled/blob/c497a62fb95c98a1e29f0eb0557ca36adcb89c7d/src/ripple/app/tx/impl/Transactor.cpp#L785-L802)
I think it's fine as-is, but I did want to bring this up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for bringing this up. So two comments:
- This cannot occur on the main network since the
featureNonFungibleTokensV1
amendment isn't active, and so theNFTokenCancelOffer
transaction cannot be executed. - In addition to the code you showed, the code will call
sterilize
on submitted transactions, which should detect this in some circumstances.
Given than we're planning to introduce another fix amendment to correct a minor issue identified with the XLS-20 implementation, which (for obvious reasons!) should be activated before XLS-20 implementation, I think my suggestion would be to include this code with this release. It doesn't need to be directly gated by the amendment, but if the fix amendment activates before featureNonFungibleTokensV1
(and again, it should), then this issue will never be able to trigger.
Apropos of this, I wonder what the performance implications of always executing the serialization/deserialization check that's currently only done if compiled with -DDEBUG
would be. Also, I wonder whether this check more properly belongs in either preflight
or preclaim
(we ought to claim a fee if someone submits a broken transaction and entomb the transation in the ledger!).
There are good reasons to have it in operator()
(i.e. during "application") too, but, as I said above, if this check fails, it would be better to tec
out of there, instead of simply calling assert
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarifications. Yeah, definitely fine as-is. 👍
The STVector256 class duplicates a lot of the std::vector interface. I think it would be simpler to declare it as:
This would allow to remove all the duplicated vector APIs (and also get the newer ones like emplace :-)) |
I disagree with publicly inheriting from |
@HowardHinnant , why do you find the implicit conversion objectionable? If we are honest, the |
If we want an implicit conversion to vector, that is one thing. But the existing API has an explicit conversion. The distinction between implicit and explicit conversions is not small. It can have a very large impact on client code that goes well beyond just syntax. We should not change the implementation to something more convenient without a full accounting of the desired API of the class. The priority of correctness is more important than the priority of ease of writing. Today, the following code is a compile-time error: auto pST = new STVector256{};
std::vector<uint256>* pv = pST;
delete pv; With the proposed change the above sequence becomes a run-time error. Compile-time errors are caught at compile-time. Run-time errors have the potential to be shipped and create problems for the XRP network. |
I'm not quite convinced that doing what I suggest is as dangerous as you make it to be, and I think there is also potential danger having extra code duplicating an API unnecessarily. But you seem to feel strongly about it, so let's leave it as is. |
I'll be honest, I've thought about this before, @greg7mdp; eliminating some of the unnecessary wrapper functions appeals to me. However there are issues: not all I think it's worth thinking about this in the broader context of classes like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 LGTM.
@greg7mdp, I addressed the comment you left. If you wouldn't mind approving this PR, thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing my comment Nik!
The existing
STVector256
is not very optimal: it requires a lot of unnecessary copying. This commit fixes that and improves detection improperly serialized values: now such values will result in an exception being raised (exceptions from that codepath are expected and properly handled).High Level Overview of Change
Context of Change
Type of Change