int -> int32_t unsigned int -> uint32_t unsigned chat -> uint8_t
Thus the implementation becomes not only unambiguous, but also more compliant with the protocol specification.
int -> int32_t unsigned int -> uint32_t unsigned chat -> uint8_t
Thus the implementation becomes not only unambiguous, but also more compliant with the protocol specification.
I would be weary of just find-replacing all int’s to int32_t’s, etc.
In my opinion they should only be converted to using {,u}int{8,16,32,64}_t if the data structure is rigidly defined to be that size. Otherwise int should be considered the default type for numerical values and long used if it would make sense and be convenient to use a 64-bit value if available.
612@@ -613,11 +613,11 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
613 class CBlockFileInfo
614 {
615 public:
616- unsigned int nBlocks; // number of blocks stored in file
617- unsigned int nSize; // number of used bytes of block file
618- unsigned int nUndoSize; // number of used bytes in the undo file
619- unsigned int nHeightFirst; // lowest height of block in file
620- unsigned int nHeightLast; // highest height of block in file
621+ uint32_t nBlocks; // number of blocks stored in file
288@@ -289,11 +289,11 @@ class CTxInUndo
289 public:
290 CTxOut txout; // the txout data before being spent
291 bool fCoinBase; // if the outpoint was the last unspent: whether it belonged to a coinbase
292- unsigned int nHeight; // if the outpoint was the last unspent: its height
293- int nVersion; // if the outpoint was the last unspent: its version
294+ uint32_t nHeight; // if the outpoint was the last unspent: its height
971@@ -972,9 +972,9 @@ class CValidationState {
972 MODE_INVALID, // network rule violation (DoS value may be set)
973 MODE_ERROR, // run-time error
974 } mode;
975- int nDoS;
976+ int32_t nDoS;
Thus the implementation becomes not only unambiguous, but also more compliant with the protocol specification.
The protocol specification is not the wiki, it’s the sourcecode. If the wiki doesn’t match that code, it should be changed - not the other way around.
Anyway, the changes look ok, but you definitely need to check case-by-case that they really cause no changes. I’d suggest writing up a report with a line or two describing each individual change. A lot of work I know, but that’s just the price of working on Bitcoin Core.
The protocol specification is not the wiki, it’s the sourcecode.
I’ll quote you every time someone on #bitcoin-dev says there is no One True Implementation.
I disagree when it’s just about the p2p protocol, as the language that two nodes speak to each other does not impact the network. When it’s about the consensus rules, it’s more complicated.
Anyway: I think in many places this is the correct thing to do. As is, the serialization framework really only works because of very strict assumptions on data type sizes. I think it’s perfectly acceptable to turn every data type that is ever serialized (appears inside a READDATA(x)) without varint or compact size into a fixed-size type.
I’ll quote you every time someone on #bitcoin-dev says there is no One True Implementation.
As you should. Those people are to a first approximation wrong. @sipa With serialization at least a change in semantics will usually fail hard and immediately - hashes won’t match. What I’d worry about more is subtle changes in semantics, e.g. overflows.
Unsigned int is 32 bit.
Also, make sure to strip the binary before comparison.
You have to take a few precautions to make sure that executables remain the same:
-frandom-seed=bitcoin
, to make sure gcc uses a deterministic random seedI may have forgotten a few. Anyhow, as said I’m willing to do the checks if you rebase this.
ACK.
Create the following patch stripbuildinfo.patch
:
0diff --git a/src/main.cpp b/src/main.cpp
1index ba521b6..8cc6fb2 100644
2--- a/src/main.cpp
3+++ b/src/main.cpp
4@@ -27,9 +27,9 @@
5 using namespace std;
6 using namespace boost;
7
8-#if defined(NDEBUG)
9-# error "Bitcoin cannot be compiled without assertions."
10-#endif
11+
12+
13+
14
15 //
16 // Global state
17diff --git a/src/version.cpp b/src/version.cpp
18index d86caa3..32dd4e9 100644
19--- a/src/version.cpp
20+++ b/src/version.cpp
21@@ -67,5 +67,5 @@ const std::string CLIENT_NAME("Satoshi");
22 # endif
23 #endif
24
25-const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
26-const std::string CLIENT_DATE(BUILD_DATE);
27+const std::string CLIENT_BUILD("");
28+const std::string CLIENT_DATE("");
Create a script do_build.sh
and chmod +x
it:
0#!/bin/bash
1git reset --hard && \
2git clean -f -x -d && \
3git checkout $1 && \
4git apply ../stripbuildinfo.patch && \
5./autogen.sh && \
6./configure --disable-wallet --without-gui --without-cli --disable-tests CPPFLAGS="-DNDEBUG -O2 -frandom-seed=bitcoin" && \
7make -j3 src/bitcoind && cp src/bitcoind ../bitcoind.$1 && \
8strip -o ../bitcoind.$1.stripped -R.note.gnu.build-id ../bitcoind.$1
0### clone the git tree
1# do this in a separate tree as the script will wipe everything inside it for sake of hygiene
2git clone https://github.com/kdomanski/bitcoin.git bitcoin-compare
3cd bitcoin-compare
4
5### build both versions
6../do_build.sh a43fde7
7../do_build.sh 003bbd5
8
9### comparison
10sha256sum ../*.stripped
(On a 64-bit Ubuntu 14.04 system) Output:
0cd7a6023a386a1abf6dc67596c58f69c7ff7549e6d6c6a31cd7097e59a4bc929 ../bitcoind.003bbd5.stripped
1cd7a6023a386a1abf6dc67596c58f69c7ff7549e6d6c6a31cd7097e59a4bc929 ../bitcoind.a43fde7.stripped
Result: OK
(On a 32-bit Ubuntu 12.04 VM) Output:
0c12d214aa09b8ea1d1ca4fd5600621fb79875650620eab1ca94f71f91068056d ../bitcoind.003bbd5.stripped
1c12d214aa09b8ea1d1ca4fd5600621fb79875650620eab1ca94f71f91068056d ../bitcoind.a43fde7.stripped
Result: OK
(Cubox-i Debian Jessie/Sid)
--with-boost-libdir=/usr/lib/arm-linux-gnueabihf
to build flags
Output:0947ceb723a99c766e99ec4a9f85769c63bb74300866f67168ccae6cb3dfeabd1 ../bitcoind.003bbd5.stripped
1947ceb723a99c766e99ec4a9f85769c63bb74300866f67168ccae6cb3dfeabd1 ../bitcoind.a43fde7.stripped
Result: OK
494@@ -495,8 +495,8 @@ class CBlock : public CBlockHeader
495
496 uint256 BuildMerkleTree() const;
497
498- std::vector<uint256> GetMerkleBranch(int nIndex) const;
499- static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex);
500+ std::vector<uint256> GetMerkleBranch(int32_t nIndex) const;
*MerkleBranch
are not directly associated with fields on the data structure that are serialized.