Skip to content

Commit dcacea0

Browse files
committed
Merge #19032: Serialization improvements: final step
71f016c Remove old serialization primitives (Pieter Wuille) 92beff1 Convert LimitedString to formatter (Pieter Wuille) ef17c03 Convert wallet to new serialization (Pieter Wuille) 65c589e Convert Qt to new serialization (Pieter Wuille) Pull request description: This is the final step 🥳 of the serialization improvements extracted from #10785. It converts the LimitedString wrapper to a new-style formatter, and updates the wallet and Qt code to use the new serialization framework. Finally all remaining old primitives are removed. ACKs for top commit: jonatack: ACK 71f016c reviewed diff, builds/tests/re-fuzzed. laanwj: Code review ACK 71f016c Tree-SHA512: d952194bc73259f6510bd4ab1348a1febbbf9862af30f905991812fb0e1f23f15948cdb3fc662be54d648e8f6d95b11060055d2e7a8c2cb5bf008224870b1ea1
2 parents fe1357a + 71f016c commit dcacea0

File tree

8 files changed

+87
-164
lines changed

8 files changed

+87
-164
lines changed

src/qt/recentrequeststablemodel.h

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,11 @@ class RecentRequestEntry
2424
QDateTime date;
2525
SendCoinsRecipient recipient;
2626

27-
ADD_SERIALIZE_METHODS;
28-
29-
template <typename Stream, typename Operation>
30-
inline void SerializationOp(Stream& s, Operation ser_action) {
31-
unsigned int nDate = date.toTime_t();
32-
33-
READWRITE(this->nVersion);
34-
READWRITE(id);
35-
READWRITE(nDate);
36-
READWRITE(recipient);
37-
38-
if (ser_action.ForRead())
39-
date = QDateTime::fromTime_t(nDate);
27+
SERIALIZE_METHODS(RecentRequestEntry, obj) {
28+
unsigned int date_timet;
29+
SER_WRITE(obj, date_timet = obj.date.toTime_t());
30+
READWRITE(obj.nVersion, obj.id, date_timet, obj.recipient);
31+
SER_READ(obj, obj.date = QDateTime::fromTime_t(date_timet));
4032
}
4133
};
4234

src/qt/sendcoinsrecipient.h

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,21 @@ class SendCoinsRecipient
4444
static const int CURRENT_VERSION = 1;
4545
int nVersion;
4646

47-
ADD_SERIALIZE_METHODS;
47+
SERIALIZE_METHODS(SendCoinsRecipient, obj)
48+
{
49+
std::string address_str, label_str, message_str, auth_merchant_str;
4850

49-
template <typename Stream, typename Operation>
50-
inline void SerializationOp(Stream& s, Operation ser_action) {
51-
std::string sAddress = address.toStdString();
52-
std::string sLabel = label.toStdString();
53-
std::string sMessage = message.toStdString();
54-
std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString();
51+
SER_WRITE(obj, address_str = obj.address.toStdString());
52+
SER_WRITE(obj, label_str = obj.label.toStdString());
53+
SER_WRITE(obj, message_str = obj.message.toStdString());
54+
SER_WRITE(obj, auth_merchant_str = obj.authenticatedMerchant.toStdString());
5555

56-
READWRITE(this->nVersion);
57-
READWRITE(sAddress);
58-
READWRITE(sLabel);
59-
READWRITE(amount);
60-
READWRITE(sMessage);
61-
READWRITE(sPaymentRequest);
62-
READWRITE(sAuthenticatedMerchant);
56+
READWRITE(obj.nVersion, address_str, label_str, obj.amount, message_str, obj.sPaymentRequest, auth_merchant_str);
6357

64-
if (ser_action.ForRead())
65-
{
66-
address = QString::fromStdString(sAddress);
67-
label = QString::fromStdString(sLabel);
68-
message = QString::fromStdString(sMessage);
69-
authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
70-
}
58+
SER_READ(obj, obj.address = QString::fromStdString(address_str));
59+
SER_READ(obj, obj.label = QString::fromStdString(label_str));
60+
SER_READ(obj, obj.message = QString::fromStdString(message_str));
61+
SER_READ(obj, obj.authenticatedMerchant = QString::fromStdString(auth_merchant_str));
7162
}
7263
};
7364

src/serialize.h

Lines changed: 8 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,6 @@ static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
4343
struct deserialize_type {};
4444
constexpr deserialize_type deserialize {};
4545

46-
/**
47-
* Used to bypass the rule against non-const reference to temporary
48-
* where it makes sense with wrappers.
49-
*/
50-
template<typename T>
51-
inline T& REF(const T& val)
52-
{
53-
return const_cast<T&>(val);
54-
}
55-
56-
/**
57-
* Used to acquire a non-const pointer "this" to generate bodies
58-
* of const serialization operations from a template
59-
*/
60-
template<typename T>
61-
inline T* NCONST_PTR(const T* val)
62-
{
63-
return const_cast<T*>(val);
64-
}
65-
6646
//! Safely convert odd char pointer types to standard ones.
6747
inline char* CharCast(char* c) { return c; }
6848
inline char* CharCast(unsigned char* c) { return (char*)c; }
@@ -193,22 +173,6 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
193173
#define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
194174
#define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
195175

196-
/**
197-
* Implement three methods for serializable objects. These are actually wrappers over
198-
* "SerializationOp" template, which implements the body of each class' serialization
199-
* code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
200-
* added as members.
201-
*/
202-
#define ADD_SERIALIZE_METHODS \
203-
template<typename Stream> \
204-
void Serialize(Stream& s) const { \
205-
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
206-
} \
207-
template<typename Stream> \
208-
void Unserialize(Stream& s) { \
209-
SerializationOp(s, CSerActionUnserialize()); \
210-
}
211-
212176
/**
213177
* Implement the Ser and Unser methods needed for implementing a formatter (see Using below).
214178
*
@@ -503,7 +467,7 @@ static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&
503467
#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
504468
#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
505469
#define COMPACTSIZE(obj) Using<CompactSizeFormatter>(obj)
506-
#define LIMITED_STRING(obj,n) LimitedString< n >(REF(obj))
470+
#define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
507471

508472
/** Serialization wrapper class for integers in VarInt format. */
509473
template<VarIntMode Mode>
@@ -588,31 +552,23 @@ struct CompactSizeFormatter
588552
};
589553

590554
template<size_t Limit>
591-
class LimitedString
555+
struct LimitedStringFormatter
592556
{
593-
protected:
594-
std::string& string;
595-
public:
596-
explicit LimitedString(std::string& _string) : string(_string) {}
597-
598557
template<typename Stream>
599-
void Unserialize(Stream& s)
558+
void Unser(Stream& s, std::string& v)
600559
{
601560
size_t size = ReadCompactSize(s);
602561
if (size > Limit) {
603562
throw std::ios_base::failure("String length limit exceeded");
604563
}
605-
string.resize(size);
606-
if (size != 0)
607-
s.read((char*)string.data(), size);
564+
v.resize(size);
565+
if (size != 0) s.read((char*)v.data(), size);
608566
}
609567

610568
template<typename Stream>
611-
void Serialize(Stream& s) const
569+
void Ser(Stream& s, const std::string& v)
612570
{
613-
WriteCompactSize(s, string.size());
614-
if (!string.empty())
615-
s.write((char*)string.data(), string.size());
571+
s << v;
616572
}
617573
};
618574

@@ -1012,7 +968,7 @@ void Unserialize(Stream& is, std::shared_ptr<const T>& p)
1012968

1013969

1014970
/**
1015-
* Support for ADD_SERIALIZE_METHODS and READWRITE macro
971+
* Support for SERIALIZE_METHODS and READWRITE macro.
1016972
*/
1017973
struct CSerActionSerialize
1018974
{

src/test/fuzz/string.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
9393
{
9494
CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
9595
std::string s;
96-
LimitedString<10> limited_string = LIMITED_STRING(s, 10);
96+
auto limited_string = LIMITED_STRING(s, 10);
9797
data_stream << random_string_1;
9898
try {
9999
data_stream >> limited_string;
@@ -108,7 +108,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
108108
}
109109
{
110110
CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
111-
const LimitedString<10> limited_string = LIMITED_STRING(random_string_1, 10);
111+
const auto limited_string = LIMITED_STRING(random_string_1, 10);
112112
data_stream << limited_string;
113113
std::string deserialized_string;
114114
data_stream >> deserialized_string;

src/wallet/crypter.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,9 @@ class CMasterKey
4343
//! such as the various parameters to scrypt
4444
std::vector<unsigned char> vchOtherDerivationParameters;
4545

46-
ADD_SERIALIZE_METHODS;
47-
48-
template <typename Stream, typename Operation>
49-
inline void SerializationOp(Stream& s, Operation ser_action) {
50-
READWRITE(vchCryptedKey);
51-
READWRITE(vchSalt);
52-
READWRITE(nDerivationMethod);
53-
READWRITE(nDeriveIterations);
54-
READWRITE(vchOtherDerivationParameters);
46+
SERIALIZE_METHODS(CMasterKey, obj)
47+
{
48+
READWRITE(obj.vchCryptedKey, obj.vchSalt, obj.nDerivationMethod, obj.nDeriveIterations, obj.vchOtherDerivationParameters);
5549
}
5650

5751
CMasterKey()

src/wallet/scriptpubkeyman.h

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -112,36 +112,37 @@ class CKeyPool
112112
CKeyPool();
113113
CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn);
114114

115-
ADD_SERIALIZE_METHODS;
115+
template<typename Stream>
116+
void Serialize(Stream& s) const
117+
{
118+
int nVersion = s.GetVersion();
119+
if (!(s.GetType() & SER_GETHASH)) {
120+
s << nVersion;
121+
}
122+
s << nTime << vchPubKey << fInternal << m_pre_split;
123+
}
116124

117-
template <typename Stream, typename Operation>
118-
inline void SerializationOp(Stream& s, Operation ser_action) {
125+
template<typename Stream>
126+
void Unserialize(Stream& s)
127+
{
119128
int nVersion = s.GetVersion();
120-
if (!(s.GetType() & SER_GETHASH))
121-
READWRITE(nVersion);
122-
READWRITE(nTime);
123-
READWRITE(vchPubKey);
124-
if (ser_action.ForRead()) {
125-
try {
126-
READWRITE(fInternal);
127-
}
128-
catch (std::ios_base::failure&) {
129-
/* flag as external address if we can't read the internal boolean
130-
(this will be the case for any wallet before the HD chain split version) */
131-
fInternal = false;
132-
}
133-
try {
134-
READWRITE(m_pre_split);
135-
}
136-
catch (std::ios_base::failure&) {
137-
/* flag as postsplit address if we can't read the m_pre_split boolean
138-
(this will be the case for any wallet that upgrades to HD chain split)*/
139-
m_pre_split = false;
140-
}
129+
if (!(s.GetType() & SER_GETHASH)) {
130+
s >> nVersion;
131+
}
132+
s >> nTime >> vchPubKey;
133+
try {
134+
s >> fInternal;
135+
} catch (std::ios_base::failure&) {
136+
/* flag as external address if we can't read the internal boolean
137+
(this will be the case for any wallet before the HD chain split version) */
138+
fInternal = false;
141139
}
142-
else {
143-
READWRITE(fInternal);
144-
READWRITE(m_pre_split);
140+
try {
141+
s >> m_pre_split;
142+
} catch (std::ios_base::failure&) {
143+
/* flag as postsplit address if we can't read the m_pre_split boolean
144+
(this will be the case for any wallet that upgrades to HD chain split) */
145+
m_pre_split = false;
145146
}
146147
}
147148
};

src/wallet/walletdb.h

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,13 @@ class CHDChain
9898
int nVersion;
9999

100100
CHDChain() { SetNull(); }
101-
ADD_SERIALIZE_METHODS;
102-
template <typename Stream, typename Operation>
103-
inline void SerializationOp(Stream& s, Operation ser_action)
101+
102+
SERIALIZE_METHODS(CHDChain, obj)
104103
{
105-
READWRITE(this->nVersion);
106-
READWRITE(nExternalChainCounter);
107-
READWRITE(seed_id);
108-
if (this->nVersion >= VERSION_HD_CHAIN_SPLIT)
109-
READWRITE(nInternalChainCounter);
104+
READWRITE(obj.nVersion, obj.nExternalChainCounter, obj.seed_id);
105+
if (obj.nVersion >= VERSION_HD_CHAIN_SPLIT) {
106+
READWRITE(obj.nInternalChainCounter);
107+
}
110108
}
111109

112110
void SetNull()
@@ -147,21 +145,16 @@ class CKeyMetadata
147145
nCreateTime = nCreateTime_;
148146
}
149147

150-
ADD_SERIALIZE_METHODS;
151-
152-
template <typename Stream, typename Operation>
153-
inline void SerializationOp(Stream& s, Operation ser_action) {
154-
READWRITE(this->nVersion);
155-
READWRITE(nCreateTime);
156-
if (this->nVersion >= VERSION_WITH_HDDATA)
157-
{
158-
READWRITE(hdKeypath);
159-
READWRITE(hd_seed_id);
148+
SERIALIZE_METHODS(CKeyMetadata, obj)
149+
{
150+
READWRITE(obj.nVersion, obj.nCreateTime);
151+
if (obj.nVersion >= VERSION_WITH_HDDATA) {
152+
READWRITE(obj.hdKeypath, obj.hd_seed_id);
160153
}
161-
if (this->nVersion >= VERSION_WITH_KEY_ORIGIN)
154+
if (obj.nVersion >= VERSION_WITH_KEY_ORIGIN)
162155
{
163-
READWRITE(key_origin);
164-
READWRITE(has_key_origin);
156+
READWRITE(obj.key_origin);
157+
READWRITE(obj.has_key_origin);
165158
}
166159
}
167160

src/wallet/walletutil.h

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,26 +98,22 @@ class WalletDescriptor
9898
int32_t next_index = 0; // Position of the next item to generate
9999
DescriptorCache cache;
100100

101-
ADD_SERIALIZE_METHODS;
102-
103-
template <typename Stream, typename Operation>
104-
inline void SerializationOp(Stream& s, Operation ser_action) {
105-
if (ser_action.ForRead()) {
106-
std::string desc;
107-
std::string error;
108-
READWRITE(desc);
109-
FlatSigningProvider keys;
110-
descriptor = Parse(desc, keys, error, true);
111-
if (!descriptor) {
112-
throw std::ios_base::failure("Invalid descriptor: " + error);
113-
}
114-
} else {
115-
READWRITE(descriptor->ToString());
101+
void DeserializeDescriptor(const std::string& str)
102+
{
103+
std::string error;
104+
FlatSigningProvider keys;
105+
descriptor = Parse(str, keys, error, true);
106+
if (!descriptor) {
107+
throw std::ios_base::failure("Invalid descriptor: " + error);
116108
}
117-
READWRITE(creation_time);
118-
READWRITE(next_index);
119-
READWRITE(range_start);
120-
READWRITE(range_end);
109+
}
110+
111+
SERIALIZE_METHODS(WalletDescriptor, obj)
112+
{
113+
std::string descriptor_str;
114+
SER_WRITE(obj, descriptor_str = obj.descriptor->ToString());
115+
READWRITE(descriptor_str, obj.creation_time, obj.next_index, obj.range_start, obj.range_end);
116+
SER_READ(obj, obj.DeserializeDescriptor(descriptor_str));
121117
}
122118

123119
WalletDescriptor() {}

0 commit comments

Comments
 (0)