mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-09 10:43:19 -05:00
Convert uses of double-serialization to {En,De}codeDouble
This commit is contained in:
parent
afd964d70b
commit
fff1cae43a
2 changed files with 46 additions and 18 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <streams.h>
|
#include <streams.h>
|
||||||
#include <txmempool.h>
|
#include <txmempool.h>
|
||||||
|
#include <util/serfloat.h>
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
|
|
||||||
static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
|
static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
|
||||||
|
@ -26,6 +27,25 @@ std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct EncodedDoubleFormatter
|
||||||
|
{
|
||||||
|
template<typename Stream> void Ser(Stream &s, double v)
|
||||||
|
{
|
||||||
|
s << EncodeDouble(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream> void Unser(Stream& s, double& v)
|
||||||
|
{
|
||||||
|
uint64_t encoded;
|
||||||
|
s >> encoded;
|
||||||
|
v = DecodeDouble(encoded);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We will instantiate an instance of this class to track transactions that were
|
* We will instantiate an instance of this class to track transactions that were
|
||||||
* included in a block. We will lump transactions into a bucket according to their
|
* 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,
|
||||||
|
|
||||||
void TxConfirmStats::Write(CAutoFile& fileout) const
|
void TxConfirmStats::Write(CAutoFile& fileout) const
|
||||||
{
|
{
|
||||||
fileout << decay;
|
fileout << Using<EncodedDoubleFormatter>(decay);
|
||||||
fileout << scale;
|
fileout << scale;
|
||||||
fileout << m_feerate_avg;
|
fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(m_feerate_avg);
|
||||||
fileout << txCtAvg;
|
fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(txCtAvg);
|
||||||
fileout << confAvg;
|
fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(confAvg);
|
||||||
fileout << failAvg;
|
fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(failAvg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets)
|
void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets)
|
||||||
|
@ -372,7 +392,7 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
|
||||||
size_t maxConfirms, maxPeriods;
|
size_t maxConfirms, maxPeriods;
|
||||||
|
|
||||||
// The current version will store the decay with each individual TxConfirmStats and also keep a scale factor
|
// The current version will store the decay with each individual TxConfirmStats and also keep a scale factor
|
||||||
filein >> decay;
|
filein >> Using<EncodedDoubleFormatter>(decay);
|
||||||
if (decay <= 0 || decay >= 1) {
|
if (decay <= 0 || decay >= 1) {
|
||||||
throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
|
throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
|
||||||
}
|
}
|
||||||
|
@ -381,15 +401,15 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
|
||||||
throw std::runtime_error("Corrupt estimates file. Scale must be non-zero");
|
throw std::runtime_error("Corrupt estimates file. Scale must be non-zero");
|
||||||
}
|
}
|
||||||
|
|
||||||
filein >> m_feerate_avg;
|
filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(m_feerate_avg);
|
||||||
if (m_feerate_avg.size() != numBuckets) {
|
if (m_feerate_avg.size() != numBuckets) {
|
||||||
throw std::runtime_error("Corrupt estimates file. Mismatch in feerate average bucket count");
|
throw std::runtime_error("Corrupt estimates file. Mismatch in feerate average bucket count");
|
||||||
}
|
}
|
||||||
filein >> txCtAvg;
|
filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(txCtAvg);
|
||||||
if (txCtAvg.size() != numBuckets) {
|
if (txCtAvg.size() != numBuckets) {
|
||||||
throw std::runtime_error("Corrupt estimates file. Mismatch in tx count bucket count");
|
throw std::runtime_error("Corrupt estimates file. Mismatch in tx count bucket count");
|
||||||
}
|
}
|
||||||
filein >> confAvg;
|
filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(confAvg);
|
||||||
maxPeriods = confAvg.size();
|
maxPeriods = confAvg.size();
|
||||||
maxConfirms = scale * maxPeriods;
|
maxConfirms = scale * maxPeriods;
|
||||||
|
|
||||||
|
@ -402,7 +422,7 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filein >> failAvg;
|
filein >> Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(failAvg);
|
||||||
if (maxPeriods != failAvg.size()) {
|
if (maxPeriods != failAvg.size()) {
|
||||||
throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures");
|
throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures");
|
||||||
}
|
}
|
||||||
|
@ -884,7 +904,7 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
|
||||||
else {
|
else {
|
||||||
fileout << historicalFirst << historicalBest;
|
fileout << historicalFirst << historicalBest;
|
||||||
}
|
}
|
||||||
fileout << buckets;
|
fileout << Using<VectorFormatter<EncodedDoubleFormatter>>(buckets);
|
||||||
feeStats->Write(fileout);
|
feeStats->Write(fileout);
|
||||||
shortStats->Write(fileout);
|
shortStats->Write(fileout);
|
||||||
longStats->Write(fileout);
|
longStats->Write(fileout);
|
||||||
|
@ -920,7 +940,7 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
|
||||||
throw std::runtime_error("Corrupt estimates file. Historical block range for estimates is invalid");
|
throw std::runtime_error("Corrupt estimates file. Historical block range for estimates is invalid");
|
||||||
}
|
}
|
||||||
std::vector<double> fileBuckets;
|
std::vector<double> fileBuckets;
|
||||||
filein >> fileBuckets;
|
filein >> Using<VectorFormatter<EncodedDoubleFormatter>>(fileBuckets);
|
||||||
size_t numBuckets = fileBuckets.size();
|
size_t numBuckets = fileBuckets.size();
|
||||||
if (numBuckets <= 1 || numBuckets > 1000) {
|
if (numBuckets <= 1 || numBuckets > 1000) {
|
||||||
throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
|
throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
#include <streams.h>
|
#include <streams.h>
|
||||||
#include <test/fuzz/FuzzedDataProvider.h>
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
#include <test/fuzz/fuzz.h>
|
#include <test/fuzz/fuzz.h>
|
||||||
|
#include <util/serfloat.h>
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
FUZZ_TARGET(float)
|
FUZZ_TARGET(float)
|
||||||
{
|
{
|
||||||
|
@ -19,12 +22,17 @@ FUZZ_TARGET(float)
|
||||||
{
|
{
|
||||||
const double d = fuzzed_data_provider.ConsumeFloatingPoint<double>();
|
const double d = fuzzed_data_provider.ConsumeFloatingPoint<double>();
|
||||||
(void)memusage::DynamicUsage(d);
|
(void)memusage::DynamicUsage(d);
|
||||||
assert(ser_uint64_to_double(ser_double_to_uint64(d)) == d);
|
|
||||||
|
|
||||||
CDataStream stream(SER_NETWORK, INIT_PROTO_VERSION);
|
uint64_t encoded = EncodeDouble(d);
|
||||||
stream << d;
|
if constexpr (std::numeric_limits<double>::is_iec559) {
|
||||||
double d_deserialized;
|
if (!std::isnan(d)) {
|
||||||
stream >> d_deserialized;
|
uint64_t encoded_in_memory;
|
||||||
assert(d == d_deserialized);
|
std::copy((const unsigned char*)&d, (const unsigned char*)(&d + 1), (unsigned char*)&encoded_in_memory);
|
||||||
|
assert(encoded_in_memory == encoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double d_deserialized = DecodeDouble(encoded);
|
||||||
|
assert(std::isnan(d) == std::isnan(d_deserialized));
|
||||||
|
assert(std::isnan(d) || d == d_deserialized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue