Skip to content

Commit fff1cae

Browse files
committed
Convert uses of double-serialization to {En,De}codeDouble
1 parent afd964d commit fff1cae

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

src/policy/fees.cpp

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <logging.h>
1111
#include <streams.h>
1212
#include <txmempool.h>
13+
#include <util/serfloat.h>
1314
#include <util/system.h>
1415

1516
static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
@@ -26,6 +27,25 @@ std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
2627
assert(false);
2728
}
2829

30+
namespace {
31+
32+
struct EncodedDoubleFormatter
33+
{
34+
template<typename Stream> void Ser(Stream &s, double v)
35+
{
36+
s << EncodeDouble(v);
37+
}
38+
39+
template<typename Stream> void Unser(Stream& s, double& v)
40+
{
41+
uint64_t encoded;
42+
s >> encoded;
43+
v = DecodeDouble(encoded);
44+
}
45+
};
46+
47+
} // namespace
48+
2949
/**
3050
* We will instantiate an instance of this class to track transactions that were
3151
* included in a block. We will lump transactions into a bucket according to their
@@ -356,12 +376,12 @@ double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal,
356376

357377
void TxConfirmStats::Write(CAutoFile& fileout) const
358378
{
359-
fileout << decay;
379+
fileout << Using<EncodedDoubleFormatter>(decay);
360380
fileout << scale;
361-
fileout << m_feerate_avg;
362-
fileout << txCtAvg;
363-
fileout << confAvg;
364-
fileout << failAvg;
381+
fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(m_feerate_avg);
382+
fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(txCtAvg);
383+
fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(confAvg);
384+
fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(failAvg);
365385
}
366386

367387
void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets)
@@ -372,7 +392,7 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
372392
size_t maxConfirms, maxPeriods;
373393

374394
// The current version will store the decay with each individual TxConfirmStats and also keep a scale factor
375-
filein >> decay;
395+
filein >> Using<EncodedDoubleFormatter>(decay);
376396
if (decay <= 0 || decay >= 1) {
377397
throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
378398
}
@@ -381,15 +401,15 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
381401
throw std::runtime_error("Corrupt estimates file. Scale must be non-zero");
382402
}
383403

384-
filein >> m_feerate_avg;
404+
filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(m_feerate_avg);
385405
if (m_feerate_avg.size() != numBuckets) {
386406
throw std::runtime_error("Corrupt estimates file. Mismatch in feerate average bucket count");
387407
}
388-
filein >> txCtAvg;
408+
filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(txCtAvg);
389409
if (txCtAvg.size() != numBuckets) {
390410
throw std::runtime_error("Corrupt estimates file. Mismatch in tx count bucket count");
391411
}
392-
filein >> confAvg;
412+
filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(confAvg);
393413
maxPeriods = confAvg.size();
394414
maxConfirms = scale * maxPeriods;
395415

@@ -402,7 +422,7 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
402422
}
403423
}
404424

405-
filein >> failAvg;
425+
filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(failAvg);
406426
if (maxPeriods != failAvg.size()) {
407427
throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures");
408428
}
@@ -884,7 +904,7 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
884904
else {
885905
fileout << historicalFirst << historicalBest;
886906
}
887-
fileout << buckets;
907+
fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
888908
feeStats->Write(fileout);
889909
shortStats->Write(fileout);
890910
longStats->Write(fileout);
@@ -920,7 +940,7 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
920940
throw std::runtime_error("Corrupt estimates file. Historical block range for estimates is invalid");
921941
}
922942
std::vector<double> fileBuckets;
923-
filein >> fileBuckets;
943+
filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
924944
size_t numBuckets = fileBuckets.size();
925945
if (numBuckets <= 1 || numBuckets > 1000) {
926946
throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");

src/test/fuzz/float.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
#include <streams.h>
88
#include <test/fuzz/FuzzedDataProvider.h>
99
#include <test/fuzz/fuzz.h>
10+
#include <util/serfloat.h>
1011
#include <version.h>
1112

1213
#include <cassert>
1314
#include <cstdint>
15+
#include <cmath>
16+
#include <limits>
1417

1518
FUZZ_TARGET(float)
1619
{
@@ -19,12 +22,17 @@ FUZZ_TARGET(float)
1922
{
2023
const double d = fuzzed_data_provider.ConsumeFloatingPoint<double>();
2124
(void)memusage::DynamicUsage(d);
22-
assert(ser_uint64_to_double(ser_double_to_uint64(d)) == d);
2325

24-
CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
25-
stream << d;
26-
double d_deserialized;
27-
stream >> d_deserialized;
28-
assert(d == d_deserialized);
26+
uint64_t encoded = EncodeDouble(d);
27+
if constexpr (std::numeric_limits<double>::is_iec559) {
28+
if (!std::isnan(d)) {
29+
uint64_t encoded_in_memory;
30+
std::copy((const unsigned char*)&d, (const unsigned char*)(&d + 1), (unsigned char*)&encoded_in_memory);
31+
assert(encoded_in_memory == encoded);
32+
}
33+
}
34+
double d_deserialized = DecodeDouble(encoded);
35+
assert(std::isnan(d) == std::isnan(d_deserialized));
36+
assert(std::isnan(d) || d == d_deserialized);
2937
}
3038
}

0 commit comments

Comments
 (0)