Skip to content

Conversation

@sipa
Copy link
Member

@sipa sipa commented Mar 20, 2018

This adds a READWRITEAS(type, obj) macro which serializes obj as if it were converted to const type& when const, and to type& when non-const. No actual cast is involved, so this only works when this conversion can be done automatically.

This makes it usable in serialization code that uses a single implementation for both serialization and deserializing, which doesn't know the constness of the object involved.

This is a redo of #12712, using a slightly different interface.

src/serialize.h Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

As x is X&&, is std::move necessary?

Copy link
Member Author

@sipa sipa Mar 20, 2018

Choose a reason for hiding this comment

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

x is a variable, and thus can't be a temporary.

The type of the expression x is X. The X&& in the function signature makes that particular instance match cases where it's invoked with a temporary as argument, but once assigned to the variable x that is gone.

Copy link
Contributor

@dcousens dcousens Mar 20, 2018

Choose a reason for hiding this comment

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

@sipa thanks, I found a verbose explanation here. I had been mislead by a previous generalization of a possible std::move implementation that lacked the cast.

src/serialize.h Outdated
Copy link
Contributor

@ryanofsky ryanofsky Mar 20, 2018

Choose a reason for hiding this comment

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

I think this may be broken in the case where x binds to the temporary result of an implicit conversion, e.g. in deserialization of ServiceFlags nServices above as int64_t, or in a more straightforward case of a char variable being deserialized as an int. In these cases the deserialization will just happen into a temporary variable, and the actual obj argument passed to READWRITEAS won't get updated.

This could be fixed with a serialization wrapper class that can deserialize into a temporary and then save the results on destruction. But a simpler alternative might just be to drop the two rvalue reference overloads of ReadWriteAsHelper so it would be an error to call READWRITEAS anywhere where deserialization would need to happen into a temporary variable. It seems like the only place where this happens is with nServices

This adds a READWRITEAS(type, obj) macro which serializes obj as if it
were casted to (const type&) when const, and to (type&) when non-const.

This makes it usable in serialization code that uses a single
implementation for both serialization and deserializing, which doesn't
know the constness of the object involved.
@sipa
Copy link
Member Author

sipa commented Mar 21, 2018

@ryanofsky Scary. I've removed the T&& overloads on the ReadWriteAsTypeHelper function, and will use a different approach for serializing ServiceFlags.

Copy link
Contributor

@eklitzke eklitzke left a comment

Choose a reason for hiding this comment

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

utACK 818dc74

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK 818dc74. Only difference since last review is potentially dangerous rvalue overloads removed, and nServices change reverted.

@laanwj
Copy link
Member

laanwj commented Apr 10, 2018

utACK 818dc74

@laanwj laanwj merged commit 818dc74 into bitcoin:master Apr 10, 2018
laanwj added a commit that referenced this pull request Apr 10, 2018
818dc74 Support serialization as another type without casting (Pieter Wuille)

Pull request description:

  This adds a `READWRITEAS(type, obj)` macro which serializes `obj` as if it were converted to `const type&` when `const`, and to `type&` when non-`const`. No actual cast is involved, so this only works when this conversion can be done automatically.

  This makes it usable in serialization code that uses a single implementation for both serialization and deserializing, which doesn't know the constness of the object involved.

  This is a redo of #12712, using a slightly different interface.

Tree-SHA512: 262f0257284ff99b5ffaec9b997c194e221522ba35c3ac8eaa9bb344449d7ea0a314de254dc77449fa7aaa600f8cd9a24da65aade8c1ec6aa80c6e9a7bba5ca7
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jun 12, 2020
…sting

818dc74 Support serialization as another type without casting (Pieter Wuille)

Pull request description:

  This adds a `READWRITEAS(type, obj)` macro which serializes `obj` as if it were converted to `const type&` when `const`, and to `type&` when non-`const`. No actual cast is involved, so this only works when this conversion can be done automatically.

  This makes it usable in serialization code that uses a single implementation for both serialization and deserializing, which doesn't know the constness of the object involved.

  This is a redo of bitcoin#12712, using a slightly different interface.

Tree-SHA512: 262f0257284ff99b5ffaec9b997c194e221522ba35c3ac8eaa9bb344449d7ea0a314de254dc77449fa7aaa600f8cd9a24da65aade8c1ec6aa80c6e9a7bba5ca7
furszy added a commit to PIVX-Project/PIVX that referenced this pull request Apr 8, 2021
172fe15 Add missing locks and locking annotations for CAddrMan (practicalswift)
9271ace Support serialization as another type without casting (Pieter Wuille)
dc37dd9 Remove unnecessary NONNEGATIVE_SIGNED (Russell Yanofsky)
ddd2ab1 Add static_assert to prevent VARINT(<signed value>) (Russell Yanofsky)
539db35 Support deserializing into temporaries (Pieter Wuille)
36db7fd Merge READWRITEMANY into READWRITE (Pieter Wuille)
08ebd5b Remove old pre C++11 functions begin_ptr/end_ptr. (furszy)
9c84665 Prevent integer overflow in ReadVarInt. (Gregory Maxwell)

Pull request description:

  Back ported some pretty concise PRs from upstream over the data serialization area.

  * bitcoin#9305.  --> removal of pre c++11 compatibility functions.
  * bitcoin#9693.  --> prevent integer overflow in `ReadVarInt`.
  * bitcoin#9753.  --> compile error if VARINT is called with a signed value.
  * bitcoin#12683. --> fixing constness violations
  * bitcoin#12731. --> support for `READWRITEAS` macro.

ACKs for top commit:
  random-zebra:
    ACK 172fe15
  Fuzzbawls:
    ACK 172fe15

Tree-SHA512: 1e1e697761b885dcc1aed8a2132bed693b1c76f1f2ed22ae5c074dfb4c353b81d307f71a4c12ed71fc39fd2207c1403881bd699e32b85a167bee57b4f0946130
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants