Skip to content

Commit 2f88cf4

Browse files
committed
Hard Fork and Many Other Improvements
- a hard fork to reduce interval of stake modifiers from 6 to 3 hours; - the block limiter improved to prevent abusive future travels; - serialisation support added for pruned transactions; - better detection and management of failed transactions; - Qt GUI minor fixes and enhancements; - various clean-ups and optimisations.
1 parent 14a8b27 commit 2f88cf4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1523
-1222
lines changed

orbitcoin-qt.pro

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
TEMPLATE = app
22
TARGET = orbitcoin-qt
3-
VERSION = 1.4.1.0
3+
VERSION = 1.4.2.0
44
INCLUDEPATH += src src/json src/qt
55
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
66
CONFIG += no_include_pwd
77
CONFIG += thread
8+
CONFIG += static
89

910
# for boost 1.37, add -mt to the boost libraries
1011
# use: qmake BOOST_LIB_SUFFIX=-mt
@@ -33,7 +34,10 @@ contains(RELEASE, 1) {
3334

3435
# for extra security on Windows: enable ASLR and DEP via GCC linker flags
3536
win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat
36-
win32:QMAKE_LFLAGS += -static-libgcc -static-libstdc++
37+
# on Windows: enable GCC large address aware linker flag
38+
win32:QMAKE_LFLAGS *= -Wl,--large-address-aware -static
39+
# i686-w64-mingw32
40+
win32:QMAKE_LFLAGS *= -static-libgcc -static-libstdc++
3741

3842
# use: qmake "USE_QRCODE=1"
3943
# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
@@ -129,7 +133,7 @@ contains(USE_O3, 1) {
129133
QMAKE_CFLAGS += -msse2
130134
}
131135

132-
QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter -Wstack-protector
136+
QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter
133137

134138
# Input
135139
DEPENDPATH += src src/json src/qt

src/checkpoints.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace Checkpoints
2727
( 0, std::make_pair(hashGenesisBlock, 1375030725) )
2828
( 433333, std::make_pair(uint256("0x2ecb07c0bb2e53f0af0bd79d24510e73de3be324e622bfef5dbe28896c37ad75"), 1392829201) )
2929
( 600000, std::make_pair(uint256("0x00000025e4214dd10eb7a4d7d088935dbc5c05b18574b56574d19c839e48e8ff"), 1398098754) )
30+
( 640000, std::make_pair(uint256("0x00000002a1fa028fb65a879c28ff66fbc4ea7dde26486c76f036315bcc17cfd7"), 1399864393) )
3031
;
3132

3233
// TestNet has no checkpoints

src/clientversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it
99
#define CLIENT_VERSION_MAJOR 1
1010
#define CLIENT_VERSION_MINOR 4
11-
#define CLIENT_VERSION_REVISION 1
11+
#define CLIENT_VERSION_REVISION 2
1212
#define CLIENT_VERSION_BUILD 0
1313

1414
// Converts the parameter X to a string after macro replacement on X has been performed.

src/init.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ CClientUIInterface uiInterface;
3030
std::string strWalletFileName;
3131
unsigned int nNodeLifespan;
3232
unsigned int nDerivationMethodIndex;
33+
unsigned int nMsgSleep;
3334
unsigned int nMinerSleep;
35+
unsigned int nStakeMinDepth;
3436
bool fUseFastIndex;
3537
bool fUseFastStakeMiner;
3638
enum Checkpoints::CPMode CheckpointsMode;
@@ -67,7 +69,7 @@ void Shutdown(void* parg)
6769
static bool fTaken;
6870

6971
// Make this thread recognisable as the shutdown thread
70-
RenameThread("orb-shutoff");
72+
RenameThread("orb-shutdown");
7173

7274
bool fFirstThread = false;
7375
{
@@ -81,25 +83,31 @@ void Shutdown(void* parg)
8183
static bool fExit;
8284
if (fFirstThread)
8385
{
86+
printf("Shutdown() : in progress...\n");
8487
fShutdown = true;
8588
nTransactionsUpdated++;
8689
bitdb.Flush(false);
8790
StopNode();
8891
{
8992
LOCK(cs_main);
90-
pcoinsTip->Flush();
91-
pblocktree->Flush();
93+
if(pwalletMain) pwalletMain->SetBestChain(CBlockLocator(pindexBest));
94+
if(pblocktree) pblocktree->Flush();
95+
if(pcoinsTip) pcoinsTip->Flush();
9296
delete pcoinsTip;
97+
pcoinsTip = NULL;
9398
delete pcoinsdbview;
99+
pcoinsdbview = NULL;
100+
delete pblocktree;
101+
pblocktree = NULL;
94102
}
95103
bitdb.Flush(true);
96104
boost::filesystem::remove(GetPidFile());
97105
UnregisterWallet(pwalletMain);
98106
delete pwalletMain;
99107
NewThread(ExitTimeout, NULL);
100108
Sleep(50);
101-
printf("Orbitcoin exited\n\n");
102109
fExit = true;
110+
printf("Shutdown() : completed\n\n");
103111
#ifndef QT_GUI
104112
// ensure non-UI client gets exited here, but let Bitcoin-Qt reach 'return 0;' in bitcoin.cpp
105113
exit(0);
@@ -368,9 +376,18 @@ bool AppInit2()
368376

369377
// ********************************************************* Step 2: parameter interactions
370378

379+
fTestNet = GetBoolArg("-testnet");
380+
if(fTestNet) SoftSetBoolArg("-irc", true);
381+
371382
nNodeLifespan = GetArg("-addrlifespan", 7);
372383
fUseFastIndex = GetBoolArg("-fastindex", true);
384+
/* Polling delay for message handling, in milliseconds */
385+
nMsgSleep = GetArg("-msgsleep", 20);
386+
/* Polling delay for stake mining, in milliseconds */
373387
nMinerSleep = GetArg("-minersleep", 500);
388+
/* Minimal input depth (age) for stake mining, in confirmations */
389+
if(fTestNet) nStakeMinDepth = GetArg("-stakemindepth", 100);
390+
else nStakeMinDepth = GetArg("-stakemindepth", 10000);
374391

375392
CheckpointsMode = Checkpoints::STRICT;
376393
std::string strCpMode = GetArg("-cppolicy", "strict");
@@ -386,11 +403,6 @@ bool AppInit2()
386403

387404
nDerivationMethodIndex = 0;
388405

389-
fTestNet = GetBoolArg("-testnet");
390-
if (fTestNet) {
391-
SoftSetBoolArg("-irc", true);
392-
}
393-
394406
if (mapArgs.count("-bind")) {
395407
// when specifying an explicit binding address, you want to listen on it
396408
// even when -connect or -proxy is specified
@@ -712,7 +724,7 @@ bool AppInit2()
712724
pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
713725

714726
if (!LoadBlockIndex())
715-
return InitError(_("Error loading blkindex.dat"));
727+
return InitError(_("Error loading block index, see debug.log for details"));
716728

717729
// as LoadBlockIndex can take several minutes, it's possible the user
718730
// requested to kill bitcoin-qt during the last operation. If so, exit.

src/kernel.cpp

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,18 @@ static bool GetLastStakeModifier(const CBlockIndex* pindex, uint64& nStakeModifi
6060
}
6161

6262
// Get selection interval section (in seconds)
63-
static int64 GetStakeModifierSelectionIntervalSection(int nSection)
63+
static int64 GetStakeModifierSelectionIntervalSection(int nSection, uint nActualModifierInterval)
6464
{
6565
assert (nSection >= 0 && nSection < 64);
66-
return (nModifierInterval * 63 / (63 + ((63 - nSection) * (MODIFIER_INTERVAL_RATIO - 1))));
66+
return (nActualModifierInterval * 63 / (63 + ((63 - nSection) * (MODIFIER_INTERVAL_RATIO - 1))));
6767
}
6868

6969
// Get stake modifier selection interval (in seconds)
70-
static int64 GetStakeModifierSelectionInterval()
70+
static int64 GetStakeModifierSelectionInterval(uint nActualModifierInterval)
7171
{
7272
int64 nSelectionInterval = 0;
7373
for (int nSection=0; nSection<64; nSection++)
74-
nSelectionInterval += GetStakeModifierSelectionIntervalSection(nSection);
74+
nSelectionInterval += GetStakeModifierSelectionIntervalSection(nSection, nActualModifierInterval);
7575
return nSelectionInterval;
7676
}
7777

@@ -152,14 +152,23 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64& nStakeModif
152152
{
153153
printf("ComputeNextStakeModifier: prev modifier=0x%016"PRI64x" time=%s\n", nStakeModifier, DateTimeStrFormat(nModifierTime).c_str());
154154
}
155-
if (nModifierTime / nModifierInterval >= pindexPrev->GetBlockTime() / nModifierInterval)
156-
return true;
155+
156+
uint nActualModifierInterval;
157+
if((fTestNet && (pindexPrev->nHeight > TESTNET_HFORK5_HEIGHT)) ||
158+
(!fTestNet && (pindexPrev->nHeight > HFORK5_HEIGHT)))
159+
nActualModifierInterval = nModifierIntervalNew;
160+
else
161+
nActualModifierInterval = nModifierInterval;
162+
163+
if((nModifierTime / nActualModifierInterval) >= (pindexPrev->GetBlockTime() / nActualModifierInterval))
164+
return(true);
157165

158166
// Sort candidate blocks by timestamp
159167
vector<pair<int64, uint256> > vSortedByTimestamp;
160-
vSortedByTimestamp.reserve(64 * nModifierInterval / nBaseTargetSpacing);
161-
int64 nSelectionInterval = GetStakeModifierSelectionInterval();
162-
int64 nSelectionIntervalStart = (pindexPrev->GetBlockTime() / nModifierInterval) * nModifierInterval - nSelectionInterval;
168+
vSortedByTimestamp.reserve(64 * nActualModifierInterval / nBaseTargetSpacing);
169+
int64 nSelectionInterval = GetStakeModifierSelectionInterval(nActualModifierInterval);
170+
int64 nSelectionIntervalStart =
171+
(pindexPrev->GetBlockTime() / nActualModifierInterval) * nActualModifierInterval - nSelectionInterval;
163172
const CBlockIndex* pindex = pindexPrev;
164173
while (pindex && pindex->GetBlockTime() >= nSelectionIntervalStart)
165174
{
@@ -177,7 +186,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64& nStakeModif
177186
for (int nRound=0; nRound<min(64, (int)vSortedByTimestamp.size()); nRound++)
178187
{
179188
// add an interval section to the current selection round
180-
nSelectionIntervalStop += GetStakeModifierSelectionIntervalSection(nRound);
189+
nSelectionIntervalStop += GetStakeModifierSelectionIntervalSection(nRound, nActualModifierInterval);
181190
// select a block from the candidates of current round
182191
if (!SelectBlockFromCandidates(vSortedByTimestamp, mapSelectedBlocks, nSelectionIntervalStop, nStakeModifier, &pindex))
183192
return error("ComputeNextStakeModifier: unable to select block at round %d", nRound);
@@ -231,7 +240,15 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier
231240
const CBlockIndex* pindexFrom = mapBlockIndex[hashBlockFrom];
232241
nStakeModifierHeight = pindexFrom->nHeight;
233242
nStakeModifierTime = pindexFrom->GetBlockTime();
234-
int64 nStakeModifierSelectionInterval = GetStakeModifierSelectionInterval();
243+
244+
uint nActualModifierInterval;
245+
if((fTestNet && (pindexFrom->nHeight > TESTNET_HFORK5_HEIGHT)) ||
246+
(!fTestNet && (pindexFrom->nHeight > HFORK5_HEIGHT)))
247+
nActualModifierInterval = nModifierIntervalNew;
248+
else
249+
nActualModifierInterval = nModifierInterval;
250+
251+
int64 nStakeModifierSelectionInterval = GetStakeModifierSelectionInterval(nActualModifierInterval);
235252
const CBlockIndex* pindex = pindexFrom;
236253
// loop to find the stake modifier later by a selection interval
237254
while (nStakeModifierTime < pindexFrom->GetBlockTime() + nStakeModifierSelectionInterval)
@@ -276,20 +293,16 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier
276293
// quantities so as to generate blocks faster, degrading the system back into
277294
// a proof-of-work situation.
278295
//
279-
bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned int nTxPrevOffset, const CTransaction& txPrev, const COutPoint& prevout, unsigned int nTimeTx, uint256& hashProofOfStake, uint256& targetProofOfStake, bool& fFatal, bool fMiner, bool fPrintProofOfStake)
280-
{
281-
if (nTimeTx < txPrev.nTime) // Transaction timestamp violation
282-
{
283-
fFatal = true;
284-
return error("CheckStakeKernelHash() : nTime violation");
285-
}
296+
bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned int nTxPrevOffset,
297+
const CTransaction& txPrev, const COutPoint& prevout, unsigned int nTimeTx, uint256& hashProofOfStake,
298+
uint256& targetProofOfStake, bool& fCritical, bool fMiner, bool fPrintProofOfStake) {
299+
300+
if(nTimeTx < txPrev.nTime)
301+
return(error("CheckStakeKernelHash() : time stamp violation"));
286302

287303
unsigned int nTimeBlockFrom = blockFrom.GetBlockTime();
288-
if (nTimeBlockFrom + nStakeMinAge > nTimeTx) // Min age requirement
289-
{
290-
fFatal = true;
291-
return error("CheckStakeKernelHash() : min age violation");
292-
}
304+
if(nTimeBlockFrom + nStakeMinAge > nTimeTx)
305+
return(error("CheckStakeKernelHash() : min. age violation"));
293306

294307
CBigNum bnTargetPerCoinDay;
295308
bnTargetPerCoinDay.SetCompact(nBits);
@@ -306,8 +319,12 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
306319
int nStakeModifierHeight = 0;
307320
int64 nStakeModifierTime = 0;
308321

309-
if (!GetKernelStakeModifier(hashBlockFrom, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake))
310-
return false;
322+
if(!GetKernelStakeModifier(hashBlockFrom, nStakeModifier, nStakeModifierHeight, nStakeModifierTime,
323+
fPrintProofOfStake)) {
324+
fCritical = false;
325+
return(false);
326+
}
327+
311328
ss << nStakeModifier;
312329

313330
ss << nTimeBlockFrom << nTxPrevOffset << txPrev.nTime << prevout.n << nTimeTx;
@@ -327,10 +344,10 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
327344
}
328345

329346
// Now check if proof-of-stake hash meets target protocol
330-
if (CBigNum(hashProofOfStake) > bnCoinDayWeight * bnTargetPerCoinDay)
331-
{
332-
fFatal = true;
333-
return !fMiner? error("CheckStakeKernelHash() : proof-of-stake not meeting target") : false;
347+
if(CBigNum(hashProofOfStake) > bnCoinDayWeight * bnTargetPerCoinDay) {
348+
/* Stake miner produces floods of these */
349+
if(!fMiner) return(error("CheckStakeKernelHash() : proof-of-stake not meeting target"));
350+
return(false);
334351
}
335352

336353
if (fDebug && !fPrintProofOfStake)
@@ -345,17 +362,16 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
345362
nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx,
346363
hashProofOfStake.ToString().c_str());
347364
}
348-
return true;
365+
366+
return(true);
349367
}
350368

351369
// Check kernel hash target and coinstake signature
352-
bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake, bool& fFatal, bool fMiner)
353-
{
354-
if (!tx.IsCoinStake())
355-
{
356-
fFatal = true;
357-
return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString().c_str());
358-
}
370+
bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake,
371+
uint256& targetProofOfStake, bool& fCritical, bool fMiner) {
372+
373+
if(!tx.IsCoinStake())
374+
return(error("CheckProofOfStake() : %s not a coin stake", tx.GetHash().ToString().c_str()));
359375

360376
// Kernel (input 0) must match the stake hash target per coin age (nBits)
361377
const CTxIn& txin = tx.vin[0];
@@ -365,8 +381,12 @@ bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hash
365381
CCoins coins;
366382
CCoinsViewCache &view = *pcoinsTip;
367383

368-
if (!view.GetCoinsReadOnly(txin.prevout.hash, coins))
369-
return fDebug? error("CheckProofOfStake() : INFO: read coins for txPrev failed") : false; // previous transaction not in main chain, may occur during initial download
384+
/* May happen if the previous transaction isn't in the main chain yet */
385+
if(!view.GetCoinsReadOnly(txin.prevout.hash, coins)) {
386+
fCritical = false;
387+
if(fDebug) return(error("CheckProofOfStake() : cannot find a previous transaction output"));
388+
return(false);
389+
}
370390

371391
CBlockIndex* pindex = FindBlockByHeight(coins.nHeight);
372392

@@ -382,34 +402,33 @@ bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hash
382402
nTxPos += tx.GetSerializeSize(SER_DISK, CLIENT_VERSION);
383403
}
384404
}
385-
else
386-
return fDebug? error("CheckProofOfStake() : read block failed") : false; // unable to read block of previous transaction
405+
else {
406+
/* May happen if the block isn't in the main chain yet */
407+
fCritical = false;
408+
if(fDebug) return(error("CheckProofOfStake() : cannot load a block requested"));
409+
return(false);
410+
}
387411

388412
const CTxOut& txout = txPrev.vout[txin.prevout.n];
389413

390414
// Check transaction consistency
391-
if (txin.prevout.n >= txPrev.vout.size())
392-
{
393-
fFatal = true;
394-
return error("CheckProofOfStake() : invalid prevout found in coinstake %s", tx.GetHash().ToString().c_str());
395-
}
415+
if(txin.prevout.n >= txPrev.vout.size())
416+
return(error("CheckProofOfStake() : coin stake %s with an invalid input",
417+
tx.GetHash().ToString().c_str()));
396418

397419
// Verify script
398-
if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, tx, 0, true, false, 0))
399-
{
400-
fFatal = true;
401-
return error("CheckProofOfStake() : VerifyScript failed on coinstake %s", tx.GetHash().ToString().c_str());
420+
if(!VerifyScript(txin.scriptSig, txout.scriptPubKey, tx, 0, true, false, 0))
421+
return(error("CheckProofOfStake() : coin stake %s script verification failed",
422+
tx.GetHash().ToString().c_str()));
423+
424+
if(!CheckStakeKernelHash(nBits, block, nTxPos, txPrev, txin.prevout, tx.nTime,
425+
hashProofOfStake, targetProofOfStake, fCritical, fMiner, fDebug)) {
426+
if(fDebug) return(error("CheckProofOfStake() : kernel check failed on coin stake %s, proof=%s",
427+
tx.GetHash().ToString().c_str(), hashProofOfStake.ToString().c_str()));
428+
return(false);
402429
}
403430

404-
if (!CheckStakeKernelHash(nBits, block, nTxPos, txPrev, txin.prevout, tx.nTime, hashProofOfStake, targetProofOfStake, fFatal, fMiner, fDebug))
405-
{
406-
if (fFatal)
407-
return false;
408-
// may occur during initial download or if behind on block chain sync
409-
return fDebug? error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString().c_str(), hashProofOfStake.ToString().c_str()) : false;
410-
}
411-
412-
return true;
431+
return(true);
413432
}
414433

415434
// Check whether the coinstake timestamp meets protocol

0 commit comments

Comments
 (0)