3
1
I'm looking through the source code of the satoshi client, particularly into how transactions are serialized and sent through the network or stored to the disk.
The CTransaction class has this block:
IMPLEMENT_SERIALIZE
(
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(vin);
READWRITE(vout);
READWRITE(nLockTime);
)
If I'm not mistaken, the serialize part of IMPLEMENT_SERIALIZE expands to:
template<typename Stream>
void Serialize(Stream& s, int nType, int nVersion) const
{
CSerActionSerialize ser_action;
const bool fGetSize = false;
const bool fWrite = true;
const bool fRead = false;
unsigned int nSerSize = 0;
assert(fGetSize||fWrite||fRead); /* suppress warning */
{
(nSerSize += ::SerReadWrite(s, (this->nVersion), nType, nVersion, ser_action))
nVersion = this->nVersion;
(nSerSize += ::SerReadWrite(s, (vin), nType, nVersion, ser_action))
(nSerSize += ::SerReadWrite(s, (vout), nType, nVersion, ser_action))
(nSerSize += ::SerReadWrite(s, (nLockTime), nType, nVersion, ser_action))
}
}
Let's focus on nLockTime for now, which is an unsigned int. SerReadWrite is defined as:
template<typename Stream, typename T>
inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
{
::Serialize(s, obj, nType, nVersion);
return 0;
}
The Serialize function, for unsigned ints is defined as:
template<typename Stream>
inline void Serialize(Stream& s, unsigned int a, int, int=0) {
WRITEDATA(s, a);
}
Which expands to:
template<typename Stream>
inline void Serialize(Stream& s, unsigned int a, int, int=0) {
s.write((char*)&(a), sizeof(a))
}
So, this converts the 4-byte unsigned int to a char* and then writes it to the stream.
However, won't this have a different result on big-endian vs. little-endian machines? How does the client handle this? Or is the protocol defined in terms of little-endian, and on the machines the satoshi client is built on, it ends up just working out?
For purposes of storing to disk, it shouldn't matter because the disk files are probably not intended to be portable. Are you sure this same code is used to send data on the network? Ignoring endianness for network data would be rather a rookie mistake. – Nate Eldredge – 2014-03-07T20:48:13.010
@NateEldredge: yep for storing disk, it shouldn't matter.
nTypeis one ofSER_NETWORK,SER_DISK, andSER_GETHASH, so I think this code is used for that as well. (it's the 3rd parameter toSerialize, not it isn't named because it's not used). It does seem like a rookie mistake, which is why I'm asking! – Claudiu – 2014-03-07T20:53:15.337"satoshi client" Do you mean Bitcoin-Qt?
– Peter Mortensen – 2014-03-08T09:09:34.907@PeterMortensen: yep! – Claudiu – 2014-03-08T09:59:05.290