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

Remove double serialization; use software encoder for fee estimation #21966

Merged
merged 6 commits into from
May 26, 2021

Conversation

sipa
Copy link
Member

@sipa sipa commented May 17, 2021

Based on #21981.

This adds a software-based platform-independent float/double encoder/decoder (platform independent in the sense that it only uses arithmetic and library calls, but never inspects the binary representation). This should strengthen our guarantee that encoded float/double values are portable across platforms. It then removes the functionality to serialize doubles from serialize.h, and replaces its only (non-test) use for fee estimation data serialization with the software encoder.

At least on x86/ARM, the only difference should be how certain NaN values are encoded/decoded (but not whether they are NaN or not).

It comes with tests that verify on is_iec559 platforms (which are the only ones we support, at least for now) that the serialized bytes exactly match the binary representation of floats in memory (for non-NaN).

@sipa sipa force-pushed the 202105_softfloat branch 2 times, most recently from f4232db to 8b0b06c Compare May 17, 2021 02:02
@sipa sipa removed the Build system label May 17, 2021
@sipa sipa force-pushed the 202105_softfloat branch from 8b0b06c to 45add0c Compare May 17, 2021 02:57
@DrahtBot
Copy link
Contributor

DrahtBot commented May 17, 2021

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@practicalswift
Copy link
Contributor

Strong Concept ACK

@laanwj
Copy link
Member

laanwj commented May 17, 2021

While I think this is intriguing technically, I'm ~0 on this conceptually

I think using floating point in places where 100% precision or portability across platforms is important is mistaken in the first place. This gives the wrong impression.

It raises deeper questions for me: do we really need floating point in Bitcoin at all? Narrower: do we really need to serialize/deserialize it?
(clearly it's already not used for anything consensus critical)

@maflcko
Copy link
Member

maflcko commented May 17, 2021

Haven't checked, but I presume it is only used for fees.dat?

@laanwj
Copy link
Member

laanwj commented May 17, 2021

If so, I'd prefer to find an alternative way of serializing those values specifically (as fixed-point or numerator / denominator pairs of integers) and dropping the general float/double (de)serialization.

@practicalswift
Copy link
Contributor

Narrower: do we really need to serialize/deserialize it?

As MarcoFalke discovered ser_float_to_uint32 and ser_uint32_to_float are currently unused (#21981), and AFAICT TxConfirmStats::Write and TxConfirmStats::Read are the only remaining users of ser_double_to_uint64 and ser_uint64_to_double.

Looks promising! :)

@sipa
Copy link
Member Author

sipa commented May 17, 2021

@laanwj That"s fair. I agree that avoiding serialization of floating point values directly is much more desirable.

My thinking here is that it effectively gives us a well-specified serialization with testable properties without needing to break compatibility with existing files.

How about rebasing this PR on top of #21981, and making it remove serialization support for double too in serialization.h, and instead make the feedata writing/reading code invoke EncodeDouble/DecodeDouble directly?

@laanwj
Copy link
Member

laanwj commented May 18, 2021

How about rebasing this PR on top of #21981, and making it remove serialization support for double too in serialization.h, and instead make the feedata writing/reading code invoke EncodeDouble/DecodeDouble directly?

I was about to comment this! Let's make this code private to the single case where it is used? It keeps the current format but also prevents future serialization of these types 😄

@sipa sipa force-pushed the 202105_softfloat branch from 45add0c to 268fe01 Compare May 18, 2021 19:47
@sipa sipa changed the title Software float encoding Remove double serialization; use software encoder for fee estimation May 18, 2021
@sipa sipa force-pushed the 202105_softfloat branch from 268fe01 to 892522d Compare May 18, 2021 19:54
@sipa
Copy link
Member Author

sipa commented May 18, 2021

@laanwj Done.

@practicalswift
Copy link
Contributor

cr ACK 892522d: patch looks correct :)

Very happy to see ser_double_to_uint64/ser_uint64_to_double go and src/compat/assumptions.h shrink :)

@laanwj
Copy link
Member

laanwj commented May 19, 2021

Thanks! Happy to see this now.

Code review ACK 892522d
Code review re-ACK 66545da

@sipa sipa force-pushed the 202105_softfloat branch from 892522d to 66545da Compare May 24, 2021 23:15
stream >> f_deserialized;
assert(f == f_deserialized);
uint64_t encoded = EncodeDouble(d);
if constexpr (std::numeric_limits<double>::is_iec559) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Note to other reviewers: We assume this to hold true in assumptions.h:

static_assert(std::numeric_limits<double>::is_iec559, "IEEE 754 double assumed");

BOOST_CHECK_EQUAL(TestDouble(785.066650390625), 0x4088888880000000ULL);

// Roundtrip test on IEC559-compatible systems
if (std::numeric_limits<double>::is_iec559) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Note to other reviewers: We assume this to hold true in assumptions.h:

static_assert(std::numeric_limits<double>::is_iec559, "IEEE 754 double assumed");

Copy link
Member Author

Choose a reason for hiding this comment

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

I should remove that assumption now, it's no longer needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need that assumption as long as we're doing floating-point division by zero? I still think we do that in ConnectBlock, CreateTransaction and EstimateMedianVal :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, good point.

Copy link
Member

@laanwj laanwj May 26, 2021

Choose a reason for hiding this comment

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

Maybe a weaker assumption could do there. In any case, it's out of scope for this PR. Happy to leave it as it is for the foreseeable future unless anyone has good reason to work on porting bitcoind to non-IEC559 platforms.

(in which case I heartily suggest: please get rid of all floating point code. it shouldn't be necessary in financial-ish code)

@practicalswift
Copy link
Contributor

cr re-ACK 66545da

@laanwj laanwj merged commit 707ba86 into bitcoin:master May 26, 2021
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request May 27, 2021
…r for fee estimation

66545da Remove support for double serialization (Pieter Wuille)
fff1cae Convert uses of double-serialization to {En,De}codeDouble (Pieter Wuille)
afd964d Convert existing float encoding tests (Pieter Wuille)
bda33f9 Add unit tests for serfloat module (Pieter Wuille)
2be4cd9 Add platform-independent float encoder/decoder (Pieter Wuille)
e40224d Remove unused float serialization (MarcoFalke)

Pull request description:

  Based on bitcoin#21981.

  This adds a software-based platform-independent float/double encoder/decoder (platform independent in the sense that it only uses arithmetic and library calls, but never inspects the binary representation). This should strengthen our guarantee that encoded float/double values are portable across platforms. It then removes the functionality to serialize doubles from serialize.h, and replaces its only (non-test) use for fee estimation data serialization with the software encoder.

  At least on x86/ARM, the only difference should be how certain NaN values are encoded/decoded (but not *whether* they are NaN or not).

  It comes with tests that verify on is_iec559 platforms (which are the only ones we support, at least for now) that the serialized bytes exactly match the binary representation of floats in memory (for non-NaN).

ACKs for top commit:
  laanwj:
    Code review re-ACK 66545da
  practicalswift:
    cr re-ACK 66545da

Tree-SHA512: 62ad9adc26e28707b2eb12a919feefd4fd10cf9032652dbb1ca1cc97638ac21de89e240858e80d293d5112685c623e58affa3d316a9783ff0e6d291977a141f5
Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

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

review ACK

kwvg pushed a commit to kwvg/dash that referenced this pull request Jun 16, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 16, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 16, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 16, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 24, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 25, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 25, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 26, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 26, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 27, 2021
kwvg added a commit to kwvg/dash that referenced this pull request Jun 27, 2021
UdjinM6 added a commit to dashpay/dash that referenced this pull request Jun 27, 2021
gades pushed a commit to cosanta/cosanta-core that referenced this pull request May 1, 2022
gwillen pushed a commit to ElementsProject/elements that referenced this pull request Jun 1, 2022
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 18, 2022
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.

5 participants