Skip to content

Commit a7c3885

Browse files
sipafurszy
authored andcommitted
Add native support for serializing char arrays without FLATDATA
Support is added to serialize arrays of type char or unsigned char directly, without any wrappers. All invocations of the FLATDATA wrappers that are obsoleted by this are removed. This includes a patch by Russell Yanofsky to make char casting type safe. The serialization of CSubNet is changed to serialize a bool directly rather than though FLATDATA. This makes the serialization independent of the size of the bool type (and will use 1 byte everywhere).
1 parent 459ecb9 commit a7c3885

File tree

8 files changed

+50
-39
lines changed

8 files changed

+50
-39
lines changed

src/addrdb.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ bool SerializeDB(Stream& stream, const Data& data)
2424
// Write and commit header, data
2525
try {
2626
CHashWriter hasher(SER_DISK, CLIENT_VERSION);
27-
stream << FLATDATA(Params().MessageStart()) << data;
28-
hasher << FLATDATA(Params().MessageStart()) << data;
27+
stream << Params().MessageStart() << data;
28+
hasher << Params().MessageStart() << data;
2929
stream << hasher.GetHash();
3030
} catch (const std::exception& e) {
3131
return error("%s: Serialize or I/O error - %s", __func__, e.what());
@@ -68,7 +68,7 @@ bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
6868
CHashVerifier<Stream> verifier(&stream);
6969
// de-serialize file header (network specific magic number) and ..
7070
unsigned char pchMsgTmp[4];
71-
verifier >> FLATDATA(pchMsgTmp);
71+
verifier >> pchMsgTmp;
7272
// ... verify the network matches ours
7373
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
7474
return error("%s: Invalid network magic number", __func__);

src/netaddress.h

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,8 @@ class CNetAddr
8484
ADD_SERIALIZE_METHODS;
8585

8686
template <typename Stream, typename Operation>
87-
inline void SerializationOp(Stream& s, Operation ser_action)
88-
{
89-
READWRITE(FLATDATA(ip));
87+
inline void SerializationOp(Stream& s, Operation ser_action) {
88+
READWRITE(ip);
9089
}
9190

9291
friend class CSubNet;
@@ -122,11 +121,10 @@ class CSubNet
122121
ADD_SERIALIZE_METHODS;
123122

124123
template <typename Stream, typename Operation>
125-
inline void SerializationOp(Stream& s, Operation ser_action)
126-
{
124+
inline void SerializationOp(Stream& s, Operation ser_action) {
127125
READWRITE(network);
128-
READWRITE(FLATDATA(netmask));
129-
READWRITE(FLATDATA(valid));
126+
READWRITE(netmask);
127+
READWRITE(valid);
130128
}
131129
};
132130

@@ -159,15 +157,14 @@ class CService : public CNetAddr
159157

160158
ADD_SERIALIZE_METHODS;
161159

162-
template <typename Stream, typename Operation>
163-
inline void SerializationOp(Stream& s, Operation ser_action)
164-
{
165-
READWRITE(FLATDATA(ip));
166-
unsigned short portN = htons(port);
167-
READWRITE(FLATDATA(portN));
168-
if (ser_action.ForRead())
169-
port = ntohs(portN);
170-
}
160+
template <typename Stream, typename Operation>
161+
inline void SerializationOp(Stream& s, Operation ser_action) {
162+
READWRITE(ip);
163+
unsigned short portN = htons(port);
164+
READWRITE(FLATDATA(portN));
165+
if (ser_action.ForRead())
166+
port = ntohs(portN);
167+
}
171168
};
172169

173170
#endif // BITCOIN_NETADDRESS_H

src/protocol.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ class CMessageHeader
4848
template <typename Stream, typename Operation>
4949
inline void SerializationOp(Stream& s, Operation ser_action)
5050
{
51-
READWRITE(FLATDATA(pchMessageStart));
52-
READWRITE(FLATDATA(pchCommand));
51+
READWRITE(pchMessageStart);
52+
READWRITE(pchCommand);
5353
READWRITE(nMessageSize);
54-
READWRITE(FLATDATA(pchChecksum));
54+
READWRITE(pchChecksum);
5555
}
5656

5757
// TODO: make private (improves encapsulation)

src/serialize.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ inline T* NCONST_PTR(const T* val)
6767
return const_cast<T*>(val);
6868
}
6969

70+
//! Safely convert odd char pointer types to standard ones.
71+
inline char* CharCast(char* c) { return c; }
72+
inline char* CharCast(unsigned char* c) { return (char*)c; }
73+
inline const char* CharCast(const char* c) { return c; }
74+
inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
75+
7076
/*
7177
* Lowest-level serialization and conversion.
7278
* @note Sizes of these types are verified in the tests
@@ -195,6 +201,8 @@ template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_wri
195201
template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
196202
template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
197203
template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
204+
template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
205+
template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
198206

199207
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
200208
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
@@ -207,6 +215,8 @@ template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a =
207215
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
208216
template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
209217
template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
218+
template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
219+
template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
210220

211221
template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
212222
template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }

src/test/net_tests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class CAddrManCorrupted : public CAddrManSerializationMock
6767
CDataStream AddrmanToStream(CAddrManSerializationMock& addrman)
6868
{
6969
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
70-
ssPeersIn << FLATDATA(Params().MessageStart());
70+
ssPeersIn << Params().MessageStart();
7171
ssPeersIn << addrman;
7272
std::string str = ssPeersIn.str();
7373
std::vector<unsigned char> vchData(str.begin(), str.end());
@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
101101
BOOST_CHECK(addrman1.size() == 0);
102102
try {
103103
unsigned char pchMsgTmp[4];
104-
ssPeers1 >> FLATDATA(pchMsgTmp);
104+
ssPeers1 >> pchMsgTmp;
105105
ssPeers1 >> addrman1;
106106
} catch (const std::exception& e) {
107107
exceptionThrown = true;
@@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
133133
BOOST_CHECK(addrman1.size() == 0);
134134
try {
135135
unsigned char pchMsgTmp[4];
136-
ssPeers1 >> FLATDATA(pchMsgTmp);
136+
ssPeers1 >> pchMsgTmp;
137137
ssPeers1 >> addrman1;
138138
} catch (const std::exception& e) {
139139
exceptionThrown = true;

src/test/serialize_tests.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,23 @@ class CSerializeMethodsTestSingle
3939
int intval;
4040
bool boolval;
4141
std::string stringval;
42-
const char* charstrval;
42+
char charstrval[16];
4343
CTransactionRef txval;
4444
public:
4545
CSerializeMethodsTestSingle() = default;
46-
CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, const CTransaction& txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), charstrval(charstrvalin), txval(MakeTransactionRef(txvalin)){}
46+
CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), txval(MakeTransactionRef(txvalin))
47+
{
48+
memcpy(charstrval, charstrvalin, sizeof(charstrval));
49+
}
50+
4751
ADD_SERIALIZE_METHODS;
4852

4953
template <typename Stream, typename Operation>
5054
inline void SerializationOp(Stream& s, Operation ser_action) {
5155
READWRITE(intval);
5256
READWRITE(boolval);
5357
READWRITE(stringval);
54-
READWRITE(FLATDATA(charstrval));
58+
READWRITE(charstrval);
5559
READWRITE(txval);
5660
}
5761

@@ -73,7 +77,7 @@ class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
7377

7478
template <typename Stream, typename Operation>
7579
inline void SerializationOp(Stream& s, Operation ser_action) {
76-
READWRITE(intval, boolval, stringval, FLATDATA(charstrval), txval);
80+
READWRITE(intval, boolval, stringval, charstrval, txval);
7781
}
7882
};
7983

@@ -370,7 +374,7 @@ BOOST_AUTO_TEST_CASE(class_methods)
370374
int intval(100);
371375
bool boolval(true);
372376
std::string stringval("testing");
373-
const char* charstrval("testing charstr");
377+
const char charstrval[16] = "testing charstr";
374378
CMutableTransaction txval;
375379
CSerializeMethodsTestSingle methodtest1(intval, boolval, stringval, charstrval, txval);
376380
CSerializeMethodsTestMany methodtest2(intval, boolval, stringval, charstrval, txval);
@@ -386,7 +390,7 @@ BOOST_AUTO_TEST_CASE(class_methods)
386390
BOOST_CHECK(methodtest2 == methodtest3);
387391
BOOST_CHECK(methodtest3 == methodtest4);
388392

389-
CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, FLATDATA(charstrval), txval);
393+
CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, charstrval, txval);
390394
ss2 >> methodtest3;
391395
BOOST_CHECK(methodtest3 == methodtest4);
392396
}

src/test/streams_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,16 @@ BOOST_AUTO_TEST_CASE(streams_vector_writer)
5353
BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
5454
vch.clear();
5555

56-
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, FLATDATA(bytes));
56+
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
5757
BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
58-
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, FLATDATA(bytes));
58+
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
5959
BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
6060
vch.clear();
6161

6262
vch.resize(4, 8);
63-
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, FLATDATA(bytes), b);
63+
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
6464
BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
65-
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, FLATDATA(bytes), b);
65+
CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
6666
BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
6767
vch.clear();
6868
}

src/validation.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos)
761761

762762
// Write index header
763763
unsigned int nSize = GetSerializeSize(fileout, block);
764-
fileout << FLATDATA(Params().MessageStart()) << nSize;
764+
fileout << Params().MessageStart() << nSize;
765765

766766
// Write block
767767
long fileOutPos = ftell(fileout.Get());
@@ -1199,7 +1199,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
11991199

12001200
// Write index header
12011201
unsigned int nSize = GetSerializeSize(fileout, blockundo);
1202-
fileout << FLATDATA(Params().MessageStart()) << nSize;
1202+
fileout << Params().MessageStart() << nSize;
12031203

12041204
// Write undo data
12051205
long fileOutPos = ftell(fileout.Get());
@@ -3916,8 +3916,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp)
39163916
// locate a header
39173917
unsigned char buf[MESSAGE_START_SIZE];
39183918
blkdat.FindByte(Params().MessageStart()[0]);
3919-
nRewind = blkdat.GetPos() + 1;
3920-
blkdat >> FLATDATA(buf);
3919+
nRewind = blkdat.GetPos()+1;
3920+
blkdat >> buf;
39213921
if (memcmp(buf, Params().MessageStart(), MESSAGE_START_SIZE))
39223922
continue;
39233923
// read size

0 commit comments

Comments
 (0)