diff --git a/Stealth.pro b/Stealth.pro
index d5d419f..d2347c8 100644
--- a/Stealth.pro
+++ b/Stealth.pro
@@ -18,7 +18,7 @@ win32 {
TEMPLATE = app
TARGET = "Stealth Qt"
-VERSION = 2.1.0.3
+VERSION = 2.2.0.0
INCLUDEPATH += src src/json src/qt src/tor
INCLUDEPATH += src/tor/adapter src/tor/common src/tor/ext
INCLUDEPATH += src/tor/ext/curve25519_donna src/tor/ext/ed25519/donna
diff --git a/contrib/macdeploy/Info.plist b/contrib/macdeploy/Info.plist
index 6f62a31..ba366d1 100644
--- a/contrib/macdeploy/Info.plist
+++ b/contrib/macdeploy/Info.plist
@@ -9,16 +9,16 @@
CFBundlePackageType
APPL
CFBundleGetInfoString
- Stealth [XST] Complete Anonymity 2.1.0.3
+ StealthCoin [XST] Complete Anonymity 2.2.0.0
CFBundleExecutable
Stealth Qt
CFBundleIdentifier
org.stealth.stealth-qt
CFBundleShortVersionString
- 2.1.0.3
+ 2.2.0.0
CFBundleSignature
oXST
CFBundleVersion
- 2.1.0.3
+ 2.2.0.0
diff --git a/src/alert.cpp b/src/alert.cpp
index 9f3ff0d..2dbc0a6 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -62,8 +62,8 @@ std::string CUnsignedAlert::ToString() const
return strprintf(
"CAlert(\n"
" nVersion = %d\n"
- " nRelayUntil = %"PRI64d"\n"
- " nExpiration = %"PRI64d"\n"
+ " nRelayUntil = %" PRI64d "\n"
+ " nExpiration = %" PRI64d "\n"
" nID = %d\n"
" nCancel = %d\n"
" setCancel = %s\n"
diff --git a/src/bignum.h b/src/bignum.h
index 9e363aa..1238f5b 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -95,12 +95,12 @@ class CBigNum
CBigNum(signed char n) { init(); if (n >= 0) setulong(n); else setint64(n); }
CBigNum(short n) { init(); if (n >= 0) setulong(n); else setint64(n); }
CBigNum(int n) { init(); if (n >= 0) setulong(n); else setint64(n); }
- CBigNum(long n) { init(); if (n >= 0) setulong(n); else setint64(n); }
+ // CBigNum(long n) { init(); if (n >= 0) setulong(n); else setint64(n); }
CBigNum(int64 n) { init(); setint64(n); }
CBigNum(unsigned char n) { init(); setulong(n); }
CBigNum(unsigned short n) { init(); setulong(n); }
CBigNum(unsigned int n) { init(); setulong(n); }
- CBigNum(size_t n) { init(); setulong((unsigned int) n); }
+ // CBigNum(size_t n) { init(); setulong((unsigned int) n); }
// CBigNum(unsigned long n) { init(); setulong(n); }
CBigNum(uint64 n) { init(); setuint64(n); }
explicit CBigNum(uint256 n) { init(); setuint256(n); }
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 54bacb9..9b0e5dc 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -403,7 +403,7 @@ static string HTTPReply(int nStatus, const string& strMsg, bool keepalive)
"HTTP/1.1 %d %s\r\n"
"Date: %s\r\n"
"Connection: %s\r\n"
- "Content-Length: %"PRIszu"\r\n"
+ "Content-Length: %" PRIszu "\r\n"
"Content-Type: application/json\r\n"
"Server: StealthCoin-json-rpc/%s\r\n"
"\r\n"
@@ -553,25 +553,33 @@ void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
bool ClientAllowed(const boost::asio::ip::address& address)
{
// Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses
- if (address.is_v6()
- && (address.to_v6().is_v4_compatible()
- || address.to_v6().is_v4_mapped()))
+ if (address.is_v6() &&
+ (address.to_v6().is_v4_compatible() ||
+ address.to_v6().is_v4_mapped()))
+ {
return ClientAllowed(address.to_v6().to_v4());
+ }
- std::string ipv4addr = address.to_string();
+ std::string ipv4addr = address.to_string();
- if (address == asio::ip::address_v4::loopback()
- || address == asio::ip::address_v6::loopback()
- || (address.is_v4()
+ if ((address == asio::ip::address_v4::loopback()) ||
+ (address == asio::ip::address_v6::loopback()) ||
+ (address.is_v4() &&
// Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet)
- && (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000))
+ (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000))
+ {
return true;
+ }
const string strAddress = address.to_string();
const vector& vAllow = mapMultiArgs["-rpcallowip"];
BOOST_FOREACH(string strAllow, vAllow)
+ {
if (WildcardMatch(strAddress, strAllow))
+ {
return true;
+ }
+ }
return false;
}
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 64fe559..ad72545 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -375,16 +375,6 @@ namespace Checkpoints
return (nBestHeight >= pindexSync->nHeight + nCoinbaseMaturity ||
pindexSync->GetBlockTime() + nStakeMinAge < GetAdjustedTime());
}
-
- // Is the sync-checkpoint too old?
- bool IsSyncCheckpointTooOld(unsigned int nSeconds)
- {
- LOCK(cs_hashSyncCheckpoint);
- // sync-checkpoint should always be accepted block
- assert(mapBlockIndex.count(hashSyncCheckpoint));
- const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint];
- return (pindexSync->GetBlockTime() + nSeconds < GetAdjustedTime());
- }
}
// stealth: sync-checkpoint master key (520 bits, 130 hex)
diff --git a/src/checkpoints.h b/src/checkpoints.h
index 4f5db11..16ec415 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -44,7 +44,6 @@ namespace Checkpoints
bool SetCheckpointPrivKey(std::string strPrivKey);
bool SendSyncCheckpoint(uint256 hashCheckpoint);
bool IsMatureSyncCheckpoint();
- bool IsSyncCheckpointTooOld(unsigned int nSeconds);
}
// ppcoin: synchronized checkpoint
diff --git a/src/clientversion.h b/src/clientversion.h
index 55df318..1d3129c 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -7,9 +7,9 @@
// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 2
-#define CLIENT_VERSION_MINOR 1
+#define CLIENT_VERSION_MINOR 2
#define CLIENT_VERSION_REVISION 0
-#define CLIENT_VERSION_BUILD 4
+#define CLIENT_VERSION_BUILD 0
// Converts the parameter X to a string after macro replacement on X has been performed.
// Don't merge these into one macro!
diff --git a/src/db.cpp b/src/db.cpp
index 72b8558..bae597a 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -462,7 +462,7 @@ void CDBEnv::Flush(bool fShutdown)
else
mi++;
}
- printf("DBFlush(%s)%s ended %15"PRI64d"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart);
+ printf("DBFlush(%s)%s ended %15" PRI64d "ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart);
if (fShutdown)
{
char** listp;
diff --git a/src/init.cpp b/src/init.cpp
index fc5b680..d361521 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -861,7 +861,7 @@ bool AppInit2()
printf("Shutdown requested. Exiting.\n");
return false;
}
- printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ printf(" block index %15" PRI64d "ms\n", GetTimeMillis() - nStart);
if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
{
@@ -952,7 +952,7 @@ bool AppInit2()
}
printf("%s", strErrors.str().c_str());
- printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ printf(" wallet %15" PRI64d "ms\n", GetTimeMillis() - nStart);
RegisterWallet(pwalletMain);
@@ -972,7 +972,7 @@ bool AppInit2()
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
nStart = GetTimeMillis();
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
- printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ printf(" rescan %15" PRI64d "ms\n", GetTimeMillis() - nStart);
}
// ********************************************************* Step 9: import blocks
@@ -1013,7 +1013,7 @@ bool AppInit2()
printf("Invalid or missing peers.dat; recreating\n");
}
- printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n",
+ printf("Loaded %i addresses from peers.dat %" PRI64d "ms\n",
addrman.size(), GetTimeMillis() - nStart);
// ********************************************************* Step 11: start node
@@ -1024,11 +1024,11 @@ bool AppInit2()
RandAddSeedPerfmon();
//// debug print
- printf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
+ printf("mapBlockIndex.size() = %" PRIszu "\n", mapBlockIndex.size());
printf("nBestHeight = %d\n", nBestHeight);
- printf("setKeyPool.size() = %"PRIszu"\n", pwalletMain->setKeyPool.size());
- printf("mapWallet.size() = %"PRIszu"\n", pwalletMain->mapWallet.size());
- printf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain->mapAddressBook.size());
+ printf("setKeyPool.size() = %" PRIszu "\n", pwalletMain->setKeyPool.size());
+ printf("mapWallet.size() = %" PRIszu "\n", pwalletMain->mapWallet.size());
+ printf("mapAddressBook.size() = %" PRIszu "\n", pwalletMain->mapAddressBook.size());
if (!NewThread(StartNode, NULL))
InitError(_("Error: could not start node"));
diff --git a/src/irc.cpp b/src/irc.cpp
index 22b2834..362331f 100644
--- a/src/irc.cpp
+++ b/src/irc.cpp
@@ -260,7 +260,7 @@ void ThreadIRCSeed2(void* parg)
if (GetLocal(addrLocal, &addrIPv4) && nNameRetry<3)
strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
if (strMyName == "")
- strMyName = strprintf("x%"PRI64u"", GetRand(1000000000));
+ strMyName = strprintf("x%" PRI64u "", GetRand(1000000000));
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str());
diff --git a/src/kernel.cpp b/src/kernel.cpp
index 5bb11fe..967a4db 100644
--- a/src/kernel.cpp
+++ b/src/kernel.cpp
@@ -130,7 +130,7 @@ static bool SelectBlockFromCandidates(
// selected block of a given block group in the past.
// The selection of a block is based on a hash of the block's proof-hash and
// the previous stake modifier.
-// Stake modifier is recomputed at a fixed time interval instead of every
+// Stake modifier is recomputed at a fixed time interval instead of every
// block. This is to make it difficult for an attacker to gain control of
// additional bits in the stake modifier, even after generating a chain of
// blocks.
@@ -150,7 +150,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64& nStakeModif
return error("ComputeNextStakeModifier: unable to get last modifier");
if (fDebug)
{
- printf("ComputeNextStakeModifier: prev modifier=0x%016"PRI64x" time=%s\n", nStakeModifier, DateTimeStrFormat(nModifierTime).c_str());
+ printf("ComputeNextStakeModifier: prev modifier=0x%016" PRI64x " time=%s\n", nStakeModifier, DateTimeStrFormat(nModifierTime).c_str());
}
if (nModifierTime / nModifierInterval >= pindexPrev->GetBlockTime() / nModifierInterval)
return true;
@@ -214,7 +214,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64& nStakeModif
}
if (fDebug)
{
- printf("ComputeNextStakeModifier: new modifier=0x%016"PRI64x" time=%s\n", nStakeModifierNew, DateTimeStrFormat(pindexPrev->GetBlockTime()).c_str());
+ printf("ComputeNextStakeModifier: new modifier=0x%016" PRI64x " time=%s\n", nStakeModifierNew, DateTimeStrFormat(pindexPrev->GetBlockTime()).c_str());
}
nStakeModifier = nStakeModifierNew;
@@ -246,7 +246,7 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier
else
{
if(fDebug)
- printf(">> nStakeModifierTime = %"PRI64d", pindexFrom->GetBlockTime() = %"PRI64d", nStakeModifierSelectionInterval = %"PRI64d"\n",
+ printf(">> nStakeModifierTime = %" PRI64d ", pindexFrom->GetBlockTime() = %" PRI64d ", nStakeModifierSelectionInterval = %" PRI64d "\n",
nStakeModifierTime, pindexFrom->GetBlockTime(), nStakeModifierSelectionInterval);
return false;
@@ -274,13 +274,13 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier
// this ensures that the chance of getting a coinstake is proportional to the
// amount of coin age one owns.
// The reason this hash is chosen is the following:
-// nStakeModifier:
+// nStakeModifier:
// (v0.3) scrambles computation to make it very difficult to precompute
// future proof-of-stake at the time of the coin's confirmation
// (v0.2) nBits (deprecated): encodes all past block timestamps
// txPrev.block.nTime: prevent nodes from guessing a good timestamp to
// generate transaction for future advantage
-// txPrev.offset: offset of txPrev inside block, to reduce the chance of
+// txPrev.offset: offset of txPrev inside block, to reduce the chance of
// nodes generating coinstake at the same time
// txPrev.nTime: reduce the chance of nodes generating coinstake at the same
// time
@@ -293,9 +293,12 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier
bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned int nTxPrevOffset, const CTransaction& txPrev, const COutPoint& prevout, unsigned int nTimeTx, uint256& hashProofOfStake, bool fPrintProofOfStake)
{
+ unsigned int nTimeTxPrev = txPrev.HasTimestamp() ?
+ txPrev.GetTxTime() : blockFrom.nTime;
+
unsigned int nTargetMultiplier = 10;
- if (nTimeTx < txPrev.nTime) // Transaction timestamp violation
+ if (nTimeTx < nTimeTxPrev) // Transaction timestamp violation
return error("CheckStakeKernelHash() : nTime violation");
unsigned int nTimeBlockFrom = blockFrom.GetBlockTime();
@@ -309,12 +312,12 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
// v0.3 protocol kernel hash weight starts from 0 at the min age
// this change increases active coins participating the hash and helps
// to secure the network when proof-of-stake difficulty is low
- int64 nTimeWeight = min((int64)nTimeTx - txPrev.nTime,
+ int64 nTimeWeight = min((int64)nTimeTx - nTimeTxPrev,
(int64)nStakeMaxAge + nStakeMinAge) -
nStakeMinAge;
CBigNum bnCoinDayWeight = CBigNum(nValueIn) * nTimeWeight / COIN / (24 * 60 * 60);
- // printf(">>> CheckStakeKernelHash: nTimeWeight = %"PRI64d"\n", nTimeWeight);
+ // printf(">>> CheckStakeKernelHash: nTimeWeight = %" PRI64d "\n", nTimeWeight);
// Calculate hash
CDataStream ss(SER_GETHASH, 0);
uint64 nStakeModifier = 0;
@@ -325,28 +328,28 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
{
if(fDebug)
printf(">>> CheckStakeKernelHash: GetKernelStakeModifier return false\n");
-
+
return false;
}
-
+
// if(fDebug) {
// printf(">>> CheckStakeKernelHash: passed GetKernelStakeModifier\n");
// }
ss << nStakeModifier;
- ss << nTimeBlockFrom << nTxPrevOffset << txPrev.nTime << prevout.n << nTimeTx;
+ ss << nTimeBlockFrom << nTxPrevOffset << nTimeTxPrev << prevout.n << nTimeTx;
hashProofOfStake = Hash(ss.begin(), ss.end());
if (fPrintProofOfStake)
{
- printf("CheckStakeKernelHash() : using modifier 0x%016"PRI64x" at height=%d timestamp=%s for block from height=%d timestamp=%s\n",
+ printf("CheckStakeKernelHash() : using modifier 0x%016" PRI64x " at height=%d timestamp=%s for block from height=%d timestamp=%s\n",
nStakeModifier, nStakeModifierHeight,
DateTimeStrFormat(nStakeModifierTime).c_str(),
mapBlockIndex[blockFrom.GetHash()]->nHeight,
DateTimeStrFormat(blockFrom.GetBlockTime()).c_str());
- printf("CheckStakeKernelHash() : check protocol=%s modifier=0x%016"PRI64x" nTimeBlockFrom=%u nTxPrevOffset=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n",
+ printf("CheckStakeKernelHash() : check protocol=%s modifier=0x%016" PRI64x " nTimeBlockFrom=%u nTxPrevOffset=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n",
"0.3",
nStakeModifier,
- nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx,
+ nTimeBlockFrom, nTxPrevOffset, nTimeTxPrev, prevout.n, nTimeTx,
hashProofOfStake.ToString().c_str());
}
@@ -354,25 +357,14 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
// The nTargetMultiplier of 10 is a calibration for stealth
CBigNum bnProduct = bnCoinDayWeight * bnTargetPerCoinDay * nTargetMultiplier;
-
-
- // someone minted with beta
- /*
- if (nTimeBlockFrom <= KERNEL_MODIFIER_TIME_01) {
- printf("\n>>> dividing by 256\n");
- hashProofOfStake = hashProofOfStake >> 8;
- }
- */
-
-
if (CBigNum(hashProofOfStake) > bnProduct)
{
if(fDebug)
{
- printf(">>> bnCoinDayWeight = %s, bnTargetPerCoinDay=%s\n>>> too small:\n",
+ printf(">>> bnCoinDayWeight = %s, bnTargetPerCoinDay=%s\n>>> too small:\n",
bnCoinDayWeight.ToString().c_str(),
bnTargetPerCoinDay.ToString().c_str(),
- bnProduct.ToString().c_str());
+ bnProduct.ToString().c_str());
printf(">>> CheckStakeKernelHash - hashProofOfStake too much\n");
printf(">>> hashProofOfStake too much: %s\n", CBigNum(hashProofOfStake).ToString().c_str());
}
@@ -382,27 +374,28 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
if (fDebug && !fPrintProofOfStake)
{
- printf("CheckStakeKernelHash() : using modifier 0x%016"PRI64x" at height=%d timestamp=%s for block from height=%d timestamp=%s\n",
- nStakeModifier, nStakeModifierHeight,
+ printf("CheckStakeKernelHash() : using modifier 0x%016" PRI64x " at height=%d timestamp=%s for block from height=%d timestamp=%s\n",
+ nStakeModifier, nStakeModifierHeight,
DateTimeStrFormat(nStakeModifierTime).c_str(),
mapBlockIndex[blockFrom.GetHash()]->nHeight,
DateTimeStrFormat(blockFrom.GetBlockTime()).c_str());
- printf("CheckStakeKernelHash() : pass protocol=%s modifier=0x%016"PRI64x" nTimeBlockFrom=%u nTxPrevOffset=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n",
+ printf("CheckStakeKernelHash() : pass protocol=%s modifier=0x%016" PRI64x " nTimeBlockFrom=%u nTxPrevOffset=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n",
"0.3",
nStakeModifier,
- nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx,
+ nTimeBlockFrom, nTxPrevOffset, nTimeTxPrev, prevout.n, nTimeTx,
hashProofOfStake.ToString().c_str());
}
return true;
}
// Check kernel hash target and coinstake signature
-bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake)
+bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits,
+ uint256& hashProofOfStake, unsigned int nBlockTime)
{
if (!tx.IsCoinStake())
return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString().c_str());
-
+ unsigned int nTimeTx = tx.HasTimestamp() ? tx.GetTxTime() : nBlockTime;
// Kernel (input 0) must match the stake hash target per coin age (nBits)
const CTxIn& txin = tx.vin[0];
@@ -425,7 +418,7 @@ bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hash
if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
return fDebug? error("CheckProofOfStake() : read block failed") : false; // unable to read block of previous transaction
- if (!CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, txPrev, txin.prevout, tx.nTime, hashProofOfStake, fDebug))
+ if (!CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, txPrev, txin.prevout, nTimeTx, hashProofOfStake, fDebug))
return tx.DoS(1, error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString().c_str(), hashProofOfStake.ToString().c_str())); // may occur during initial download or if behind on block chain sync
return true;
@@ -450,7 +443,7 @@ unsigned int GetStakeModifierChecksum(const CBlockIndex* pindex)
uint256 hashChecksum = Hash(ss.begin(), ss.end());
hashChecksum >>= (256 - 32);
if(fDebug)
- printf("stake checksum: 0x%016"PRI64x"\n", hashChecksum.Get64());
+ printf("stake checksum: 0x%016" PRI64x "\n", hashChecksum.Get64());
return hashChecksum.Get64();
}
diff --git a/src/kernel.h b/src/kernel.h
index 631664a..f81dd72 100644
--- a/src/kernel.h
+++ b/src/kernel.h
@@ -23,7 +23,8 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
// Check kernel hash target and coinstake signature
// Sets hashProofOfStake on success return
-bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake);
+bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits,
+ uint256& hashProofOfStake, unsigned int nBlockTime);
// Check whether the coinstake timestamp meets protocol
bool CheckCoinStakeTimestamp(int64 nTimeBlock, int64 nTimeTx);
@@ -37,7 +38,4 @@ bool CheckStakeModifierCheckpoints(int nHeight, unsigned int nStakeModifierCheck
// Get time weight using supplied timestamps
int64 GetWeight(int64 nIntervalBeginning, int64 nIntervalEnd);
-// shit happens - someone minted with a beta wallet
-static const int64 KERNEL_MODIFIER_TIME_01 = 1406227020 + 60 * 60 * 2;
-
#endif // PPCOIN_KERNEL_H
diff --git a/src/key.cpp b/src/key.cpp
index a2be4cb..80a3306 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -379,9 +379,9 @@ bool CKey::Sign(uint256 hash, std::vector& vchSig)
sig_s_new = BN_new();
// enforce low S values, by negating the value (modulo the order) if above order/2.
BN_sub(sig_s_new, order, sig_s);
+ BN_copy(sig_r_new, sig_r);
// no need to free sig_*_new according to OpenSSL docs
// https://www.openssl.org/docs/man1.1.0/crypto/ECDSA_SIG_set0.html
- BN_copy(sig_r_new, sig_r);
ECDSA_SIG_set0(sig, sig_r_new, sig_s_new);
}
#else
diff --git a/src/main.cpp b/src/main.cpp
index a667e9c..e4d796f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -41,11 +41,11 @@ static CBigNum bnProofOfWorkLimit(~uint256(0) >> 20);
static CBigNum bnProofOfStakeLimit(~uint256(0) >> 2);
static CBigNum bnProofOfWorkLimitTestNet(~uint256(0) >> 16);
-static CBigNum bnProofOfStakeLimitTestNet(~uint256(0) >> 30);
+static CBigNum bnProofOfStakeLimitTestNet(~uint256(0) >> 2);
-unsigned int nStakeMinAge = 60 * 60 * 24 * 3; //minimum age for coin age: 3 day
-unsigned int nStakeMaxAge = 60 * 60 * 24 * 9; //stake age of full weight: 9 day
-unsigned int nStakeTargetSpacing = 60; // 60 sec block spacing
+unsigned int nStakeMinAge = 60 * 60 * 24 * 3; //minimum age for coin age: 3 day
+unsigned int nStakeMaxAge = 60 * 60 * 24 * 9; //stake age of full weight: 9 day
+unsigned int nStakeTargetSpacing = 60; // 60 sec block spacing
int64 nChainStartTime = 1403684997;
int nCoinbaseMaturity = 40;
@@ -90,27 +90,33 @@ int64 nReserveBalance = 0;
int GetFork(int nHeight)
{
// Make sure Heights are ascending!
- const int aForks[TOTAL_FORKS][2] = {
- // Height, Fork Number
- /* Jul 4 02:47:04 MDT 2014 */ { 1, XST_LAUNCH },
- /* 08/16/2017 */ { 1732201, XST_FORK005 }
- };
-
- if (fTestNet)
- {
- return TOTAL_FORKS;
- }
-
+ const int aForks[2][TOTAL_FORKS][2] =
+ {
+ /* MAIN NET */ { // Height, Fork Number
+ /* Jul 4 02:47:04 MDT 2014 */ { 0, XST_GENESIS },
+ /* Oct 9 00:00:42 MST 2014 */ { 130669, XST_FORK004 },
+ /* Aug 16 10:23:28 MDT 2017 */ { 1732201, XST_FORK005 },
+ /* Approx Nov 14, MDT 2018 */ { 2378000, XST_FORK006 }
+ },
+ /* TEST NET */ { // Height, Fork Number
+ { 0, XST_GENESIS },
+ { 0, XST_FORK004 },
+ { 40, XST_FORK005 },
+ { 145, XST_FORK006 }
+ }
+ };
+
// loop has strange logic, but if fork i height is greater than nHeight
// then you are on fork i-1
- int nFork = aForks[0][1];
+ const int idx = fTestNet ? 1 : 0;
+ int nFork = aForks[idx][0][1];
for (int i = 1; i < TOTAL_FORKS; ++i)
{
- if (aForks[i][0] > nHeight)
+ if (aForks[idx][i][0] > nHeight)
{
break;
}
- nFork = aForks[i][1];
+ nFork = aForks[idx][i][1];
}
return nFork;
}
@@ -124,13 +130,14 @@ int GetFork(int nHeight)
int GetMinPeerProtoVersion(int nHeight)
{
// helps to prevent buffer overrun
- static const int nVersions = 2;
+ static const int nVersions = 3;
// Make sure forks are ascending!
const int aVersions[nVersions][2] = {
// Fork, Proto Version
- { XST_LAUNCH, 62020 },
- { XST_FORK005, 62100 }
+ { XST_GENESIS, 62020 },
+ { XST_FORK005, 62100 },
+ { XST_FORK006, 62200 }
};
int nFork = GetFork(nHeight);
@@ -187,7 +194,7 @@ bool static IsFromMe(CTransaction& tx)
bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- if (pwallet->GetTransaction(hashTx,wtx))
+ if (pwallet->GetTransaction(hashTx, wtx))
return true;
return false;
}
@@ -279,7 +286,7 @@ bool AddOrphanTx(const CDataStream& vMsg)
// at most 500 megabytes of orphans:
if (pvMsg->size() > 5000)
{
- printf("ignoring large orphan tx (size: %"PRIszu", hash: %s)\n", pvMsg->size(), hash.ToString().substr(0,10).c_str());
+ printf("ignoring large orphan tx (size: %" PRIszu ", hash: %s)\n", pvMsg->size(), hash.ToString().substr(0,10).c_str());
delete pvMsg;
return false;
}
@@ -288,7 +295,7 @@ bool AddOrphanTx(const CDataStream& vMsg)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(make_pair(hash, pvMsg));
- printf("stored orphan tx %s (mapsz %"PRIszu")\n", hash.ToString().substr(0,10).c_str(),
+ printf("stored orphan tx %s (mapsz %" PRIszu ")\n", hash.ToString().substr(0,10).c_str(),
mapOrphanTransactions.size());
return true;
}
@@ -364,7 +371,9 @@ bool CTransaction::ReadFromDisk(COutPoint prevout)
bool CTransaction::IsStandard() const
{
if (nVersion > CTransaction::CURRENT_VERSION)
+ {
return false;
+ }
if (GetFork(nBestHeight + 1) >= XST_FORK005)
{
@@ -380,7 +389,8 @@ bool CTransaction::IsStandard() const
// the next block.
//
// However, IsFinalTx() is confusing... Without arguments, it uses
- // chainActive.Height() to evaluate nLockTime; when a block is accepted, chainActive.Height()
+ // chainActive.Height() to evaluate nLockTime; when a block is
+ // accepted, chainActive.Height()
// is set to the value of nHeight in the block. However, when IsFinalTx()
// is called within CBlock::AcceptBlock(), the height of the block *being*
// evaluated is what is used. Thus if we want to know if a transaction can
@@ -393,8 +403,13 @@ bool CTransaction::IsStandard() const
if (!IsFinal(nBestHeight + 1)) {
return false;
}
- // nTime has different purpose from nLockTime but can be used in similar attacks
- if (nTime > FutureDrift(GetAdjustedTime())) {
+
+ // nTime, aka GetTxTime(), has a different purpose from nLockTime
+ // but can be used in similar attacks
+ // CTransaction gets timestamp from block upon NOTXTIME_VERSION
+ // block timestamp checked elsewhere
+ if (HasTimestamp() && (GetTxTime() > FutureDrift(GetAdjustedTime())))
+ {
return false;
}
@@ -574,8 +589,6 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
}
-
-
bool CTransaction::CheckTransaction() const
{
// Basic checks that don't depend on any context
@@ -595,12 +608,14 @@ bool CTransaction::CheckTransaction() const
if (txout.IsEmpty() && !IsCoinBase() && !IsCoinStake())
return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction"));
- if (fTestNet || (nTime >= STEALTH_ADDR_KICK_IN))
+ if (GetFork(nBestHeight+1) >= XST_FORK004)
{
if (txout.nValue < 0)
return DoS(100,
error("CTransaction::CheckTransaction() : txout.nValue negative"));
- }else {
+ }
+ else
+ {
if ((!txout.IsEmpty()) && txout.nValue < MIN_TXOUT_AMOUNT)
return DoS(100,
error("CTransaction::CheckTransaction() : txout.nValue below minimum"));
@@ -760,7 +775,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx,
// Don't accept it if it can't get into a block
int64 txMinFee = tx.GetMinFee(1000, false, GMF_RELAY, nSize);
if (nFees < txMinFee)
- return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d,
+ return error("CTxMemPool::accept() : not enough fees %s, %" PRI64d " < %" PRI64d,
hash.ToString().c_str(),
nFees, txMinFee);
@@ -798,7 +813,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx,
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!tx.ConnectInputs(txdb, mapInputs, mapUnused, CDiskTxPos(1,1,1),
- pindexBest, false, false, flags))
+ pindexBest, false, false, flags))
{
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
}
@@ -820,7 +835,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx,
if (ptxOld)
EraseFromWallets(ptxOld->GetHash());
- printf("CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n",
+ printf("CTxMemPool::accept() : accepted %s (poolsz %" PRIszu ")\n",
hash.ToString().substr(0,10).c_str(),
mapTx.size());
return true;
@@ -905,8 +920,6 @@ void CTxMemPool::queryHashes(std::vector& vtxid)
}
-
-
int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
{
if (hashBlock == 0 || nIndex == -1)
@@ -968,8 +981,6 @@ bool CMerkleTx::AcceptToMemoryPool()
return AcceptToMemoryPool(txdb);
}
-
-
bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
{
@@ -990,7 +1001,6 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
return false;
}
-
bool CWalletTx::AcceptWalletTransaction()
{
CTxDB txdb("r");
@@ -1015,7 +1025,8 @@ int CTxIndex::GetDepthInMainChain() const
}
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
-bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock)
+bool GetTransaction(const uint256 &hash, CTransaction &tx,
+ uint256 &hashBlock, unsigned int &nTimeBlock)
{
{
LOCK(cs_main);
@@ -1032,7 +1043,10 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock)
{
CBlock block;
if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
+ {
hashBlock = block.GetHash();
+ nTimeBlock = block.GetBlockTime();
+ }
return true;
}
}
@@ -1100,7 +1114,7 @@ uint256 WantedByOrphan(const CBlock* pblockOrphan)
int generateMTRandom(unsigned int s, int range)
{
- random::mt19937 gen(s);
+ random::mt19937 gen(s);
random::uniform_int_distribution<> dist(0, range);
return dist(gen);
}
@@ -1112,58 +1126,44 @@ int64 GetProofOfWorkReward(int nHeight, int64 nFees, uint256 prevHash)
{
int64 nSubsidy = 0 * COIN;
- if (nHeight == 0)
- nSubsidy = 16 * COIN; // genesis block coinbase is unspendable
- else if (nHeight <= 10)
- nSubsidy = 23300 * COIN; // Blocks 1-10 are premine
- else if (nHeight <= 260)
- nSubsidy = 16 * COIN; // 4 hr Low Reward Period for Fairness
- else if (nHeight <= 1700)
- nSubsidy = 8000 * COIN;
- else if (nHeight <= 3140)
- nSubsidy = 4000 * COIN;
- else if (nHeight <= 4580)
- nSubsidy = 2000 * COIN;
- else if (nHeight < CUTOFF_POW_BLOCK)
- nSubsidy = 1000 * COIN; // was 1 coin
-/*
- else if (nHeight <= 6020)
- nSubsidy = 1000 * COIN;
- else if (nHeight <= 7460)
- nSubsidy = 500 * COIN;
- else if (nHeight <= 8900)
- nSubsidy = 250 * COIN;
- else if (nHeight <= 10340)
- nSubsidy = 125 * COIN;
- else if (nHeight <= 11780)
- nSubsidy = 62 * COIN;
- else if (nHeight <= 13220)
- nSubsidy = 31 * COIN;
- else if (nHeight <= 14660)
- nSubsidy = 15 * COIN;
- else if (nHeight <= 16100)
- nSubsidy = 8 * COIN;
- else if (nHeight <= 17540)
- nSubsidy = 4 * COIN;
- else if (nHeight <= 18980)
- nSubsidy = 2 * COIN;
- else if (nHeight < CUTOFF_POW_BLOCK)
- nSubsidy = 1 * COIN;
- */
+ if (fTestNet)
+ {
+ if (nHeight == 0)
+ nSubsidy = 16 * COIN;
+ else if (nHeight < GetPoWCutoff())
+ nSubsidy = 90000 * COIN;
+ }
+ else
+ {
+ if (nHeight == 0)
+ nSubsidy = 16 * COIN; // genesis block coinbase is unspendable
+ else if (nHeight <= 10)
+ nSubsidy = 23300 * COIN; // Blocks 1-10 are premine
+ else if (nHeight <= 260)
+ nSubsidy = 16 * COIN; // 4 hr Low Reward Period for Fairness
+ else if (nHeight <= 1700)
+ nSubsidy = 8000 * COIN;
+ else if (nHeight <= 3140)
+ nSubsidy = 4000 * COIN;
+ else if (nHeight <= 4580)
+ nSubsidy = 2000 * COIN;
+ else if (nHeight < GetPoWCutoff())
+ nSubsidy = 1000 * COIN; // was 1 coin
+ }
return nSubsidy + nFees;
}
// miner's coin stake reward based on nBits and coin age spent (coin-days)
// simple algorithm, not depend on the diff
-int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime, int nHeight)
+int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, int nHeight)
{
int64 nRewardCoinYear;
- nRewardCoinYear = MAX_STEALTH_PROOF_OF_STAKE;
+ nRewardCoinYear = fTestNet ? MAX_STEALTH_PROOF_OF_STAKE_TESTNET : MAX_STEALTH_PROOF_OF_STAKE;
int64 nSubsidy = nCoinAge * nRewardCoinYear / 365;
if (fDebug && GetBoolArg("-printcreation"))
- printf("GetProofOfStakeReward(): create=%s nCoinAge=%"PRI64d" nBits=%d\n", FormatMoney(nSubsidy).c_str(), nCoinAge, nBits);
+ printf("GetProofOfStakeReward(): create=%s nCoinAge=%" PRI64d " nBits=%d\n", FormatMoney(nSubsidy).c_str(), nCoinAge, nBits);
return nSubsidy;
}
@@ -1239,16 +1239,16 @@ unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfS
return bnTargetLimit.GetCompact(); // second block
int64 nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();
- if(nActualSpacing < 0)
- {
- // printf(">> nActualSpacing = %"PRI64d" corrected to 1.\n", nActualSpacing);
- nActualSpacing = 1;
- }
- else if(nActualSpacing > nTargetTimespan)
- {
- // printf(">> nActualSpacing = %"PRI64d" corrected to nTargetTimespan (900).\n", nActualSpacing);
- nActualSpacing = nTargetTimespan;
- }
+ if(nActualSpacing < 0)
+ {
+ // printf(">> nActualSpacing = %" PRI64d " corrected to 1.\n", nActualSpacing);
+ nActualSpacing = 1;
+ }
+ else if(nActualSpacing > nTargetTimespan)
+ {
+ // printf(">> nActualSpacing = %" PRI64d " corrected to nTargetTimespan (900).\n", nActualSpacing);
+ nActualSpacing = nTargetTimespan;
+ }
// ppcoin: target change every block
// ppcoin: retarget with exponential moving toward target spacing
@@ -1259,13 +1259,6 @@ unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfS
int64 nInterval = nTargetTimespan / nTargetSpacing;
bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
bnNew /= ((nInterval + 1) * nTargetSpacing);
-
- /*
- printf(">> Height = %d, fProofOfStake = %d, nInterval = %"PRI64d", nTargetSpacing = %"PRI64d", nActualSpacing = %"PRI64d"\n",
- pindexPrev->nHeight, fProofOfStake, nInterval, nTargetSpacing, nActualSpacing);
- printf(">> pindexPrev->GetBlockTime() = %"PRI64d", pindexPrev->nHeight = %d, pindexPrevPrev->GetBlockTime() = %"PRI64d", pindexPrevPrev->nHeight = %d\n",
- pindexPrev->GetBlockTime(), pindexPrev->nHeight, pindexPrevPrev->GetBlockTime(), pindexPrevPrev->nHeight);
- */
if (bnNew > bnTargetLimit)
bnNew = bnTargetLimit;
@@ -1440,7 +1433,7 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTes
// Revisit this if/when transaction replacement is implemented and allows
// adding inputs:
fInvalid = true;
- return DoS(100, error("FetchInputs() : %s prevout.n out of range %d %"PRIszu" %"PRIszu" prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()));
+ return DoS(100, error("FetchInputs() : %s prevout.n out of range %d %" PRIszu " %" PRIszu " prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()));
}
}
@@ -1501,6 +1494,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs,
// fBlock is true when this is called from AcceptBlock when a new best-block is added to the blockchain
// fMiner is true when called from the internal bitcoin miner
// ... both are false when called from CTransaction::AcceptToMemoryPool
+ unsigned int nTxTime = HasTimestamp() ? GetTxTime() : pindexBlock->nTime;
if (!IsCoinBase())
{
int64 nValueIn = 0;
@@ -1513,17 +1507,29 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs,
CTransaction& txPrev = inputs[prevout.hash].second;
if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
- return DoS(100, error("ConnectInputs() : %s prevout.n out of range %d %"PRIszu" %"PRIszu" prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()));
+ return DoS(100, error("ConnectInputs() : %s prevout.n out of range %d %" PRIszu " %" PRIszu " prev tx %s\n%s", GetHash().ToString().substr(0,10).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString().substr(0,10).c_str(), txPrev.ToString().c_str()));
// If prev is coinbase or coinstake, check that it's matured
if (txPrev.IsCoinBase() || txPrev.IsCoinStake())
+ {
for (const CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < nCoinbaseMaturity; pindex = pindex->pprev)
+ {
if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile)
+ {
return error("ConnectInputs() : tried to spend %s at depth %d", txPrev.IsCoinBase() ? "coinbase" : "coinstake", pindexBlock->nHeight - pindex->nHeight);
+ }
+ }
+ }
- // ppcoin: check transaction timestamp
- if (txPrev.nTime > nTime)
- return DoS(100, error("ConnectInputs() : transaction timestamp earlier than input transaction"));
+ // check is meaningless if one or the other has no timestamp
+ if (txPrev.HasTimestamp() && HasTimestamp())
+ {
+ // ppcoin: check transaction timestamp
+ if (txPrev.GetTxTime() > nTxTime)
+ {
+ return DoS(100, error("ConnectInputs() : transaction timestamp earlier than input transaction"));
+ }
+ }
if (txPrev.vout[prevout.n].IsEmpty() && (GetFork(nBestHeight + 1) >= XST_FORK005))
{
@@ -1579,10 +1585,10 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs,
{
// ppcoin: coin stake tx earns reward instead of paying fee
uint64 nCoinAge;
- if (!GetCoinAge(txdb, nCoinAge))
+ if (!GetCoinAge(txdb, pindexBlock->nTime, nCoinAge))
return error("ConnectInputs() : %s unable to get coin age for coinstake", GetHash().ToString().substr(0,10).c_str());
int64 nStakeReward = GetValueOut() - nValueIn;
- if (nStakeReward > GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, nTime, pindexBlock->nHeight) - GetMinFee() + MIN_TX_FEE)
+ if (nStakeReward > GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, pindexBlock->nHeight) - GetMinFee() + MIN_TX_FEE)
return DoS(100, error("ConnectInputs() : %s stake reward exceeded", GetHash().ToString().substr(0,10).c_str()));
}
else
@@ -1607,7 +1613,6 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs,
return true;
}
-
bool CTransaction::ClientConnectInputs()
{
if (IsCoinBase())
@@ -1629,7 +1634,7 @@ bool CTransaction::ClientConnectInputs()
return false;
unsigned int flags = STANDARD_SCRIPT_VERIFY_FLAGS;
- if (GetFork(nBestHeight+1) < XST_FORK005)
+ if (GetFork(nBestHeight + 1) < XST_FORK005)
{
flags = flags & ~SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
}
@@ -1638,16 +1643,6 @@ bool CTransaction::ClientConnectInputs()
if (!VerifySignature(txPrev, *this, i, flags, 0))
return error("ConnectInputs() : VerifySignature failed");
- ///// this is redundant with the mempool.mapNextTx stuff,
- ///// not sure which I want to get rid of
- ///// this has to go away now that posNext is gone
- // // Check for conflicts
- // if (!txPrev.vout[prevout.n].posNext.IsNull())
- // return error("ConnectInputs() : prev tx already used");
- //
- // // Flag outpoints as used
- // txPrev.vout[prevout.n].posNext = posThisTx;
-
nValueIn += txPrev.vout[prevout.n].nValue;
if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
@@ -1688,10 +1683,10 @@ bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)
bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
{
// Check it again in case a previous version let a bad block in
- if (!CheckBlock(!fJustCheck, !fJustCheck))
+ if (!CheckBlock(pindex->nHeight, !fJustCheck, !fJustCheck))
return false;
unsigned int flags = SCRIPT_VERIFY_NOCACHE | STANDARD_SCRIPT_VERIFY_FLAGS;
- if (GetFork(nBestHeight+1) < XST_FORK005)
+ if (GetFork(nBestHeight + 1) < XST_FORK005)
{
flags = flags & ~SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
}
@@ -1789,7 +1784,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
// ppcoin: fees are not collected by miners as in bitcoin
// ppcoin: fees are destroyed to compensate the entire network
if (fDebug && GetBoolArg("-printcreation"))
- printf("ConnectBlock() : destroy=%s nFees=%"PRI64d"\n", FormatMoney(nFees).c_str(), nFees);
+ printf("ConnectBlock() : destroy=%s nFees=%" PRI64d "\n", FormatMoney(nFees).c_str(), nFees);
if (fJustCheck)
return true;
@@ -1805,13 +1800,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
if(pindex->pprev)
{
prevHash = pindex->pprev->GetBlockHash();
- // printf("==> Got prevHash = %s\n", prevHash.ToString().c_str());
}
- // if (vtx[0].GetValueOut() > GetProofOfWorkReward(
- // (unsigned int) pindex->nHeight, nFees, prevHash))
- // return false;
-
// Update block index on disk without changing it in memory.
// The memory index structure will be changed after the db commits.
if (pindex->pprev)
@@ -1858,8 +1848,8 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
vConnect.push_back(pindex);
reverse(vConnect.begin(), vConnect.end());
- printf("REORGANIZE: Disconnect %"PRIszu" blocks; %s..%s\n", vDisconnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexBest->GetBlockHash().ToString().substr(0,20).c_str());
- printf("REORGANIZE: Connect %"PRIszu" blocks; %s..%s\n", vConnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->GetBlockHash().ToString().substr(0,20).c_str());
+ printf("REORGANIZE: Disconnect %" PRIszu " blocks; %s..%s\n", vDisconnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexBest->GetBlockHash().ToString().substr(0,20).c_str());
+ printf("REORGANIZE: Connect %" PRIszu " blocks; %s..%s\n", vConnect.size(), pfork->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->GetBlockHash().ToString().substr(0,20).c_str());
// Disconnect shorter branch
list vResurrect;
@@ -1929,7 +1919,6 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
return true;
}
-
// Called from inside SetBestChain: attaches a block to the new best chain being built
bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew)
{
@@ -1992,7 +1981,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
}
if (!vpindexSecondary.empty())
- printf("Postponing %"PRIszu" reconnects\n", vpindexSecondary.size());
+ printf("Postponing %" PRIszu " reconnects\n", vpindexSecondary.size());
// Switch to new best branch
if (!Reorganize(txdb, pindexIntermediate))
@@ -2041,7 +2030,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
hashBestChain.ToString().c_str(), nBestHeight, bnBestChainTrust.ToString().c_str(),
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
- printf("Stake checkpoint: %x\n", pindexBest->nStakeModifierChecksum);
+ printf("Stake checkpoint: %x\n", pindexBest->nStakeModifierChecksum);
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
@@ -2079,7 +2068,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
// guaranteed to be in main chain by sync-checkpoint. This rule is
// introduced to help nodes establish a consistent view of the coin
// age (trust score) of competing branches.
-bool CTransaction::GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const
+bool CTransaction::GetCoinAge(CTxDB& txdb, unsigned int nBlockTime, uint64& nCoinAge) const
{
CBigNum bnCentSecond = 0; // coin age in the unit of cent-seconds
nCoinAge = 0;
@@ -2089,29 +2078,41 @@ bool CTransaction::GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const
if (IsCoinBase())
return true;
+ unsigned int nTxTime = HasTimestamp() ? GetTxTime() : nBlockTime;
+
BOOST_FOREACH(const CTxIn& txin, vin)
{
// First try finding the previous transaction in database
CTransaction txPrev;
CTxIndex txindex;
if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
+ {
continue; // previous transaction not in main chain
- if (nTime < txPrev.nTime)
- return false; // Transaction timestamp violation
-
+ }
// Read block header
CBlock block;
if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
+ {
return false; // unable to read block of previous transaction
- if (block.GetBlockTime() + nStakeMinAge > nTime)
+ }
+ unsigned int nBlockTime = block.GetBlockTime();
+ unsigned int nTxPrevTime = txPrev.HasTimestamp() ?
+ txPrev.GetTxTime() : nBlockTime;
+ if (nTxTime < nTxPrevTime)
+ {
+ return false; // Transaction timestamp violation
+ }
+
+ if (nBlockTime + nStakeMinAge > nTxTime)
continue; // only count coins meeting min age requirement
int64 nValueIn = txPrev.vout[txin.prevout.n].nValue;
- bnSeconds = min(CBigNum(nTime-txPrev.nTime), MAX_COIN_SECONDS);
+ bnSeconds = min(CBigNum(nTxTime - nTxPrevTime), MAX_COIN_SECONDS);
bnCentSecond += CBigNum(nValueIn) * bnSeconds / CENT;
if (fDebug && GetBoolArg("-printcoinage"))
- printf("coin age nValueIn=%"PRI64d" nTimeDiff=%d bnCentSecond=%s\n", nValueIn, nTime - txPrev.nTime, bnCentSecond.ToString().c_str());
+ printf("coin age nValueIn=%" PRI64d " nTimeDiff=%d bnCentSecond=%s\n",
+ nValueIn, nTxTime - nTxPrevTime, bnCentSecond.ToString().c_str());
}
@@ -2131,16 +2132,20 @@ bool CBlock::GetCoinAge(uint64& nCoinAge) const
BOOST_FOREACH(const CTransaction& tx, vtx)
{
uint64 nTxCoinAge;
- if (tx.GetCoinAge(txdb, nTxCoinAge))
+ if (tx.GetCoinAge(txdb, nTime, nTxCoinAge))
+ {
nCoinAge += nTxCoinAge;
+ }
else
+ {
return false;
+ }
}
if (nCoinAge == 0) // block coin age minimum 1 coin-day
nCoinAge = 1;
if (fDebug && GetBoolArg("-printcoinage"))
- printf("block coin age total nCoinDays=%"PRI64d"\n", nCoinAge);
+ printf("block coin age total nCoinDays=%" PRI64d "\n", nCoinAge);
return true;
}
@@ -2183,7 +2188,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const u
pindexNew->SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
pindexNew->nStakeModifierChecksum = GetStakeModifierChecksum(pindexNew);
if (!CheckStakeModifierCheckpoints(pindexNew->nHeight, pindexNew->nStakeModifierChecksum))
- return error("AddToBlockIndex() : Rejected by stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindexNew->nHeight, nStakeModifier);
+ return error("AddToBlockIndex() : Rejected by stake modifier checkpoint height=%d, modifier=0x%016" PRI64x, pindexNew->nHeight, nStakeModifier);
// Add to mapBlockIndex
map::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
@@ -2219,90 +2224,137 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const u
}
-bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot,
- bool fCheckSig) const
+bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) const
{
// These are checks that are independent of context
// that can be verified before saving an orphan block.
// Size limits
- if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE ||
+ ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ {
return DoS(100, error("CheckBlock() : size limits failed"));
+ }
// Check proof of work matches claimed amount
if (fCheckPOW && IsProofOfWork() && !CheckProofOfWork(GetHash(), nBits))
+ {
return DoS(50, error("CheckBlock() : proof of work failed"));
+ }
+
+ int nFork = GetFork(nBestHeight + 1);
// Check timestamp
- if (GetFork(nBestHeight + 1) >= XST_FORK005)
+ if (nFork >= XST_FORK005)
{
if (GetBlockTime() > FutureDrift(GetAdjustedTime()))
+ {
return error("CheckBlock() : block timestamp too far in the future");
+ }
}
else
{
if (GetBlockTime() > GetAdjustedTime() + nMaxClockDrift)
+ {
return error("CheckBlock() : block timestamp too far in the future");
+ }
}
// First transaction must be coinbase, the rest must not be
if (vtx.empty() || !vtx[0].IsCoinBase())
+ {
return DoS(100, error("CheckBlock() : first tx is not coinbase"));
+ }
for (unsigned int i = 1; i < vtx.size(); i++)
+ {
if (vtx[i].IsCoinBase())
+ {
return DoS(100, error("CheckBlock() : more than one coinbase"));
-
+ }
+ }
// Check coinbase timestamp
- if (GetFork(nBestHeight + 1) >= XST_FORK005)
+ if (nFork < XST_FORK005)
{
- if (GetBlockTime() > FutureDrift((int64)vtx[0].nTime))
- return DoS(50, error("CheckBlock() : coinbase timestamp: %" PRI64d " + 15 sec, "
- "is too early for block: %" PRI64d,
- (int64)vtx[0].nTime, (int64)GetBlockTime()));
+ // prior to XST_FORK006 CTransactions have timestamps
+ if (GetBlockTime() > (int64)vtx[0].GetTxTime() + nMaxClockDrift)
+ {
+ return DoS(50, error("CheckBlock() : coinbase timestamp is too early"));
+ }
}
- else
+ // exclude pow because
+ // (1) testnet usually has too few miners to stay in future drift
+ // (2) main net mining is done, so there is no need to check drift,
+ // and also the future drift was much more at the time
+ // this probably should be fixed "the right way" one day
+ else if (vtx[0].HasTimestamp() && !IsProofOfWork())
{
- if (GetBlockTime() > (int64)vtx[0].nTime + nMaxClockDrift)
- return DoS(50, error("CheckBlock() : coinbase timestamp is too early"));
+ if (GetBlockTime() > FutureDrift((int64)vtx[0].GetTxTime()))
+ {
+ return DoS(50, error("CheckBlock() : coinbase timestamp: %" PRI64d " + 15 sec, "
+ "is too early for block: %" PRI64d,
+ (int64)vtx[0].GetTxTime(), (int64)GetBlockTime()));
+ }
}
if (IsProofOfStake())
{
if (vtx[0].vout.size() != 1 || !vtx[0].vout[0].IsEmpty())
+ {
return DoS(100,
error("CheckBlock() : coinbase output not empty for proof-of-stake block"));
+ }
// Second transaction must be coinstake, the rest must not be
if (vtx.empty() || !vtx[1].IsCoinStake())
+ {
return DoS(100, error("CheckBlock() : second tx is not coinstake"));
+ }
for (unsigned int i = 2; i < vtx.size(); i++)
+ {
if (vtx[i].IsCoinStake())
+ {
return DoS(100, error("CheckBlock() : more than one coinstake"));
+ }
+ }
- // Check coinstake timestamp
-if (!CheckCoinStakeTimestamp(GetBlockTime(), (int64)vtx[1].nTime))
- return DoS(50,
- error("CheckBlock() : coinstake timestamp violation nTimeBlock=%"
- PRI64d " nTimeTx=%u", GetBlockTime(), vtx[1].nTime));
+ // Check coinstake timestamp
+ // no check upon XST_FORK006 because tx timestamps eliminated,
+ // effectivly making tx same as block
+ if (vtx[1].HasTimestamp() &&
+ (!CheckCoinStakeTimestamp(GetBlockTime(), (int64)vtx[1].GetTxTime())))
+ {
+ return DoS(50,
+ error("CheckBlock() : coinstake timestamp violation nTimeBlock=%"
+ PRI64d " nTimeTx=%u", GetBlockTime(), vtx[1].GetTxTime()));
+ }
- if ((nTime >= CUTOFF_POW_TIME) && (IsProofOfWork()))
- return DoS(100, error("CheckBlock() : Proof of work (%f XST) at t=%d on or after %d.\n",
- ((double) vtx[0].GetValueOut() / (double) COIN),
- (int) nTime,
- (int) CUTOFF_POW_TIME));
- if (fCheckSig & !CheckBlockSignature())
- return DoS(100, error("CheckBlock() : bad proof-of-stake block signature"));
+ if (((nBestHeight + 1) >= GetPoWCutoff()) && (IsProofOfWork()))
+ {
+ return DoS(100, error("CheckBlock() : Proof of work (%f XST) at t=%d on or after block %d.\n",
+ ((double) vtx[0].GetValueOut() / (double) COIN),
+ (int) nTime,
+ (int) GetPoWCutoff()));
+ }
+ if (fCheckSig & !CheckBlockSignature())
+ {
+ return DoS(100, error("CheckBlock() : bad proof-of-stake block signature"));
+ }
}
// Check transactions
BOOST_FOREACH(const CTransaction& tx, vtx)
{
if (!tx.CheckTransaction())
+ {
return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed"));
+ }
// ppcoin: check transaction timestamp
- if (GetBlockTime() < (int64)tx.nTime)
+ // ignore as of XST_FORK006 as tx timestamps are thereupon eliminated
+ if (tx.HasTimestamp() && (GetBlockTime() < (int64)tx.GetTxTime()))
+ {
return DoS(50, error("CheckBlock() : block timestamp earlier than transaction timestamp"));
+ }
}
// Check for duplicate txids. This is caught by ConnectInputs(),
@@ -2345,17 +2397,28 @@ bool CBlock::AcceptBlock()
CBlockIndex* pindexPrev = (*mi).second;
int nHeight = pindexPrev->nHeight+1;
- if (IsProofOfWork() && (nHeight > CUTOFF_POW_BLOCK))
+ if (IsProofOfWork() && (nHeight > GetPoWCutoff()))
return DoS(100, error("AcceptBlock() : No proof-of-work allowed anymore (height = %d)", nHeight));
if (GetFork(nBestHeight + 1) >= XST_FORK005)
{
- // Check coinbase timestamp
- if (GetBlockTime() > FutureDrift((int64)vtx[0].nTime))
- return DoS(50, error("AcceptBlock() : coinbase timestamp is too early"));
- // Check coinstake timestamp
- if (IsProofOfStake() && !CheckCoinStakeTimestamp(GetBlockTime(), (int64)vtx[1].nTime))
- return DoS(50, error("AcceptBlock() : coinstake timestamp violation nTimeBlock=%" PRI64d " nTimeTx=%u", GetBlockTime(), vtx[1].nTime));
+ if (vtx[0].HasTimestamp())
+ {
+ // Check coinbase timestamp
+ if (GetBlockTime() > FutureDrift((int64)vtx[0].GetTxTime()))
+ {
+ return DoS(50, error("AcceptBlock() : coinbase timestamp is too early"));
+ }
+ }
+ if (vtx[1].HasTimestamp())
+ {
+ // Check coinstake timestamp
+ if (IsProofOfStake() && !CheckCoinStakeTimestamp(GetBlockTime(), (int64)vtx[1].GetTxTime()))
+ {
+ return DoS(50, error("AcceptBlock() : coinstake timestamp violation nTimeBlock=%" PRI64d
+ " nTimeTx=%u", GetBlockTime(), vtx[1].GetTxTime()));
+ }
+ }
}
// Check proof-of-work or proof-of-stake
@@ -2388,7 +2451,7 @@ bool CBlock::AcceptBlock()
if (IsProofOfStake())
{
uint256 targetProofOfStake;
- if (!CheckProofOfStake(vtx[1], nBits, hashProof))
+ if (!CheckProofOfStake(vtx[1], nBits, hashProof, nTime))
{
printf("WARNING: AcceptBlock(): check proof-of-stake failed for block %s\n", hash.ToString().c_str());
return false; // do not error here as we expect this during initial block download
@@ -2414,10 +2477,6 @@ bool CBlock::AcceptBlock()
}
}
- // Reject block.nVersion < 3 blocks since 95% threshold on mainNet and always on testNet:
- if (nVersion < 3 && ((!fTestNet && nHeight > 14060) || (fTestNet && nHeight > 0)))
- return error("CheckBlock() : rejected nVersion < 3 block");
-
// Enforce rule that the coinbase starts with serialized block height
CScript expect = CScript() << nHeight;
if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
@@ -2484,7 +2543,6 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
bool ProcessBlock(CNode* pfrom, CBlock* pblock, bool fIsBootstrap)
-// bool ProcessBlock(CNode* pfrom, CBlock* pblock)
{
// Check for duplicate
uint256 hash = pblock->GetHash();
@@ -2500,32 +2558,33 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock, bool fIsBootstrap)
if (pblock->IsProofOfStake() && setStakeSeen.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash) && !Checkpoints::WantedByPendingSyncCheckpoint(hash) & !fIsBootstrap)
return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for block %s", pblock->GetProofOfStake().first.ToString().c_str(), pblock->GetProofOfStake().second, hash.ToString().c_str());
- // Preliminary checks
- if (!pblock->CheckBlock())
- return error("ProcessBlock() : CheckBlock FAILED");
CBlockLocator locator;
int nHeight = locator.GetBlockIndex()->nHeight;
- if (pblock->IsProofOfWork() && (nHeight >= CUTOFF_POW_BLOCK)) {
+ // Preliminary checks
+ if (!pblock->CheckBlock(nHeight))
+ return error("ProcessBlock() : CheckBlock FAILED");
+
+ if (pblock->IsProofOfWork() && (nHeight >= GetPoWCutoff())) {
if (pfrom)
pfrom->Misbehaving(100);
- printf("Proof of work on or after block %d.\n", CUTOFF_POW_BLOCK);
- return error("Proof of work on or after block %d.\n", CUTOFF_POW_BLOCK);
+ printf("Proof of work on or after block %d.\n", GetPoWCutoff());
+ return error("Proof of work on or after block %d.\n", GetPoWCutoff());
}
CBlockIndex* pcheckpoint = Checkpoints::GetLastSyncCheckpoint();
if(pcheckpoint && fDebug)
{
- const CBlockIndex* pindexLastPos = GetLastBlockIndex(pcheckpoint, true);
+ const CBlockIndex* pindexLastPos = GetLastBlockIndex(pcheckpoint, true);
if(pindexLastPos)
- {
+ {
printf("ProcessBlock(): Last POS Block Height: %d \n", pindexLastPos->nHeight);
- }
- else
- {
- printf("ProcessBlock(): Previous POS block not found.\n");
- }
+ }
+ else
+ {
+ printf("ProcessBlock(): Previous POS block not found.\n");
+ }
}
if (pcheckpoint && pblock->hashPrevBlock != hashBestChain && !Checkpoints::WantedByPendingSyncCheckpoint(hash))
@@ -2541,7 +2600,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock, bool fIsBootstrap)
if (pblock->IsProofOfStake()) {
bnRequired.SetCompact(ComputeMinStake(nLastBits, deltaTime, pblock->nTime));
- if ((nThisHeight < CUTOFF_POW_BLOCK) && (bnNewBlock > bnProofOfStakeLimit)) {
+ if ((nThisHeight < GetPoWCutoff()) && (bnNewBlock > bnProofOfStakeLimit)) {
bnNewBlock = bnNewBlock >> 2; // adjust target for big hashes
}
}
@@ -2816,18 +2875,18 @@ bool LoadBlockIndex(bool fAllowNew)
{
if (fTestNet)
{
- pchMessageStart[0] = 0x70;
- pchMessageStart[1] = 0x35;
- pchMessageStart[2] = 0x22;
- pchMessageStart[3] = 0x05;
+ pchMessageStart[0] = 0xcf;
+ pchMessageStart[1] = 0xed;
+ pchMessageStart[2] = 0xff;
+ pchMessageStart[3] = 0xfd;
bnProofOfStakeLimit = bnProofOfStakeLimitTestNet; // 0x00000fff PoS base target is fixed in testnet
bnProofOfWorkLimit = bnProofOfWorkLimitTestNet; // 0x0000ffff PoW base target is fixed in testnet
- nStakeMinAge = 15 * 60; // test net min age is 20 min
- nStakeMaxAge = 60 * 60; // test net min age is 60 min
- nModifierInterval = 60; // test modifier interval is 2 minutes
+ nStakeMinAge = 1 * 60; // test net min age is 1 min
+ nStakeMaxAge = 40 * 60; // test net min age is 40 min
+ nModifierInterval = 30; // test modifier interval is 30 seconds
nCoinbaseMaturity = 10; // test maturity is 10 blocks
- nStakeTargetSpacing = 3 * 60; // test block spacing is 3 minutes
+ nStakeTargetSpacing = 20; // test block spacing is 20 seconds
}
//
@@ -2849,7 +2908,7 @@ bool LoadBlockIndex(bool fAllowNew)
// Genesis block
const char* pszTimestamp = "20140615 Stealth proves that pzTimestamp is overkill.";
CTransaction txNew;
- txNew.nTime = nChainStartTime;
+ txNew.SetTxTime(nChainStartTime);
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(9999) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
@@ -2864,20 +2923,20 @@ bool LoadBlockIndex(bool fAllowNew)
block.nBits = bnProofOfWorkLimit.GetCompact();
block.nNonce = 4204204204LL; // perfect nonce
- if (false && (block.GetHash() != hashGenesisBlock)) {
-
- // This will figure out a valid hash and Nonce if you're
- // creating a different genesis block:
+ if (false && (block.GetHash() != hashGenesisBlock))
+ {
+ // This will figure out a valid hash and Nonce if you're
+ // creating a different genesis block:
uint256 hashTarget = CBigNum().SetCompact(block.nBits).getuint256();
while (block.GetHash() > hashTarget)
- {
- ++block.nNonce;
- if (block.nNonce == 0)
- {
- printf("NONCE WRAPPED, incrementing time");
- ++block.nTime;
- }
- }
+ {
+ ++block.nNonce;
+ if (block.nNonce == 0)
+ {
+ printf("NONCE WRAPPED, incrementing time");
+ ++block.nTime;
+ }
+ }
}
//// debug print
@@ -2887,8 +2946,11 @@ bool LoadBlockIndex(bool fAllowNew)
printf("block.nTime = %u \n", block.nTime);
printf("block.nNonce = %u \n", block.nNonce);
- assert(block.hashMerkleRoot == uint256("0xe3de7c386d5b82f62ff24c6d2351539c22b17c6ffab0e267b3cdd72fda82bd83"));
- assert(block.GetHash() == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet));
+ uint256 hashMerkleRootMainNet("0xe3de7c386d5b82f62ff24c6d2351539c22b17c6ffab0e267b3cdd72fda82bd83");
+ uint256 hashMerkleRootTestNet("0xe3de7c386d5b82f62ff24c6d2351539c22b17c6ffab0e267b3cdd72fda82bd83");
+
+ assert(block.hashMerkleRoot == (fTestNet ? hashMerkleRootTestNet : hashMerkleRootMainNet));
+ assert(block.GetHash() == (fTestNet ? hashGenesisBlockTestNet : hashGenesisBlock));
// Start new block file
unsigned int nFile;
@@ -2918,14 +2980,11 @@ bool LoadBlockIndex(bool fAllowNew)
if ((!fTestNet) && !Checkpoints::ResetSyncCheckpoint())
return error("LoadBlockIndex() : failed to reset sync-checkpoint");
}
- //txdb.Close();
}
return true;
}
-
-
void PrintBlockTree()
{
// pre-compute tree structure
@@ -2934,9 +2993,6 @@ void PrintBlockTree()
{
CBlockIndex* pindex = (*mi).second;
mapNext[pindex->pprev].push_back(pindex);
- // test
- //while (rand() % 3 == 0)
- // mapNext[pindex->pprev].push_back(pindex);
}
vector > vStack;
@@ -2971,7 +3027,7 @@ void PrintBlockTree()
// print item
CBlock block;
block.ReadFromDisk(pindex);
- printf("%d (%u,%u) %s %08x %s mint %7s tx %"PRIszu"",
+ printf("%d (%u,%u) %s %08x %s mint %7s tx %" PRIszu "",
pindex->nHeight,
pindex->nFile,
pindex->nBlockPos,
@@ -3057,7 +3113,7 @@ bool LoadExternalBlockFile(FILE* fileIn)
__PRETTY_FUNCTION__);
}
}
- printf("Loaded %i blocks from external file in %"PRI64d"ms\n", nLoaded, GetTimeMillis() - nStart);
+ printf("Loaded %i blocks from external file in %" PRI64d "ms\n", nLoaded, GetTimeMillis() - nStart);
if (GetBoolArg("-quitonbootstrap", false))
{
exit(EXIT_SUCCESS);
@@ -3092,14 +3148,6 @@ string GetWarnings(string strFor)
strStatusBar = strMiscWarning;
}
- // ppcoin: should not enter safe mode for longer invalid chain
- // ppcoin: if sync-checkpoint is too old do not enter safe mode
- if (Checkpoints::IsSyncCheckpointTooOld(60 * 60 * 24 * 365) && !fTestNet && !IsInitialBlockDownload())
- {
- nPriority = 100;
- strStatusBar = "WARNING: Checkpoint is too old. Wait for block chain to download, or notify developers.";
- }
-
// ppcoin: if detected invalid checkpoint enter safe mode
if (Checkpoints::hashInvalidCheckpoint != 0)
{
@@ -3181,7 +3229,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
static map mapReuseKey;
RandAddSeedPerfmon();
if (fDebug)
- printf("received: %s (%"PRIszu" bytes)\n", strCommand.c_str(), vRecv.size());
+ printf("received: %s (%" PRIszu " bytes)\n", strCommand.c_str(), vRecv.size());
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
printf("dropmessagestest DROPPING RECV MESSAGE\n");
@@ -3223,7 +3271,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (pfrom->nVersion < GetMinPeerProtoVersion(nBestHeight))
{
// disconnect from peers older than this proto version
- printf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString().c_str(), pfrom->nVersion);
+ printf("partner %s using obsolete version %i; disconnecting\n",
+ pfrom->addr.ToString().c_str(), pfrom->nVersion);
pfrom->fDisconnect = true;
return false;
}
@@ -3237,13 +3286,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (!vRecv.empty())
vRecv >> pfrom->nStartingHeight;
- // if (!vRecv.empty())
- // // set to true after we get the first filter* message
- // vRecv >> pfrom->fRelayTxes;
- // else
- // pfrom->fRelayTxes = true;
-
-
if (pfrom->fInbound && addrMe.IsRoutable())
{
pfrom->addrLocal = addrMe;
@@ -3376,7 +3418,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (vAddr.size() > 1000)
{
pfrom->Misbehaving(20);
- return error("message addr size() = %"PRIszu"", vAddr.size());
+ return error("message addr size() = %" PRIszu "", vAddr.size());
}
// Store the new addresses
@@ -3439,7 +3481,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (vInv.size() > MAX_INV_SZ)
{
pfrom->Misbehaving(20);
- return error("message inv size() = %"PRIszu"", vInv.size());
+ return error("message inv size() = %" PRIszu "", vInv.size());
}
// find last block in inv vector
@@ -3489,11 +3531,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (vInv.size() > MAX_INV_SZ)
{
pfrom->Misbehaving(20);
- return error("message getdata size() = %"PRIszu"", vInv.size());
+ return error("message getdata size() = %" PRIszu "", vInv.size());
}
if (fDebugNet || (vInv.size() != 1))
- printf("received getdata (%"PRIszu" invsz)\n", vInv.size());
+ printf("received getdata (%" PRIszu " invsz)\n", vInv.size());
BOOST_FOREACH(const CInv& inv, vInv)
{
@@ -3894,21 +3936,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
bool ProcessMessages(CNode* pfrom)
{
- if (fDebug) {
- printf("ProcessMessages: %s\n",
- pfrom->addr.ToString().c_str());
- }
+ // if (fDebug) {
+ // printf("ProcessMessages: %s\n",
+ // pfrom->addr.ToString().c_str());
+ // }
CDataStream& vRecv = pfrom->vRecv;
if (vRecv.empty()) {
- if (fDebug)
- {
- printf("ProcessMessages: %s [empty]\n",
- pfrom->addr.ToString().c_str());
- }
+ // if (fDebug)
+ // {
+ // printf("ProcessMessages: %s [empty]\n",
+ // pfrom->addr.ToString().c_str());
+ // }
return true;
}
- //if (fDebug)
- // printf("ProcessMessages(%u bytes)\n", vRecv.size());
//
// Message format
@@ -3938,7 +3978,7 @@ bool ProcessMessages(CNode* pfrom)
break;
}
if (pstart - vRecv.begin() > 0)
- printf("\n\nPROCESSMESSAGE SKIPPED %"PRIpdd" BYTES\n\n", pstart - vRecv.begin());
+ printf("\n\nPROCESSMESSAGE SKIPPED %" PRIpdd " BYTES\n\n", pstart - vRecv.begin());
vRecv.erase(vRecv.begin(), pstart);
// Read header
@@ -4203,7 +4243,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
//////////////////////////////////////////////////////////////////////////////
//
-// BitcoinMiner
+// StealthMinter
//
int static FormatHashBlocks(void* pbuffer, unsigned int len)
@@ -4222,7 +4262,10 @@ int static FormatHashBlocks(void* pbuffer, unsigned int len)
}
static const unsigned int pSHA256InitState[8] =
-{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+ {0x6a09e667, 0xbb67ae85,
+ 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c,
+ 0x1f83d9ab, 0x5be0cd19};
void SHA256Transform(void* pstate, void* pinput, const void* pinit)
{
@@ -4302,9 +4345,16 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake)
CReserveKey reservekey(pwallet);
// Create new block
- auto_ptr pblock(new CBlock());
+ #if __cplusplus >= 201103L
+ unique_ptr pblock(new CBlock());
+ #else
+ auto_ptr pblock(new CBlock());
+ #endif
+
if (!pblock.get())
+ {
return NULL;
+ }
CBlockIndex* pindexPrev = pindexBest;
@@ -4341,35 +4391,62 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake)
// cost to you of processing a transaction.
int64 nMinTxFee = MIN_TX_FEE;
if (mapArgs.count("-mintxfee"))
+ {
ParseMoney(mapArgs["-mintxfee"], nMinTxFee);
+ }
+
+ int nFork = GetFork(nHeight);
// ppcoin: if coinstake available add coinstake tx
- static int64 nLastCoinStakeSearchTime = GetAdjustedTime(); // only initialized at startup
+ // only initialized at startup
+ static unsigned int nLastCoinStakeSearchTime = (unsigned int) GetAdjustedTime();
+
+ unsigned int nCoinStakeTime = (unsigned int) GetAdjustedTime();
if (fProofOfStake) // attempt to find a coinstake
{
pblock->nBits = GetNextTargetRequired(pindexPrev, true);
CTransaction txCoinStake;
- int64 nSearchTime = txCoinStake.nTime; // search to current time
+
+ // Upon XST_FORK006, transactions don't have meaningful timestamps.
+ // However to use the logic of this function for now, nCoinStakeTime will
+ // be used to hold the block timestamp. Upon XST_FORK006, the block
+ // timestamp will be a permanent record of its transaction timestamps.
+ if (txCoinStake.HasTimestamp())
+ {
+ txCoinStake.SetTxTime(nCoinStakeTime);
+ }
+
+ unsigned int nSearchTime = nCoinStakeTime; // search to current time
if (nSearchTime > nLastCoinStakeSearchTime)
{
- // printf(">>> OK1\n");
- if (pwallet->CreateCoinStake(*pwallet, pblock->nBits, nSearchTime-nLastCoinStakeSearchTime, txCoinStake))
+ if (pwallet->CreateCoinStake(*pwallet, pblock->nBits,
+ nSearchTime - nLastCoinStakeSearchTime, txCoinStake, nCoinStakeTime))
{
- int nTimeMax;
- if (GetFork(nHeight) >= XST_FORK005)
+ unsigned int nTimeMax;
+ if (nFork < XST_FORK005)
{
- nTimeMax = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime());
+ nTimeMax = max(pindexPrev->GetPastTimeLimit()+1, pindexPrev->GetBlockTime() - nMaxClockDrift);
}
else
{
- nTimeMax = max(pindexPrev->GetPastTimeLimit()+1, pindexPrev->GetBlockTime() - nMaxClockDrift);
+ if (nFork >= XST_FORK006)
+ {
+ pblock->nTime = nCoinStakeTime;
+ }
+ nTimeMax = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime());
}
- if (txCoinStake.nTime >= (unsigned int) nTimeMax)
+
+ if (nCoinStakeTime >= nTimeMax)
{ // make sure coinstake would meet timestamp protocol
// as it would be the same as the block timestamp
pblock->vtx[0].vout[0].SetEmpty();
- pblock->vtx[0].nTime = txCoinStake.nTime;
+ // this test simply marks that assinging tx ntime upon creation
+ // will be eliminated in the future
+ if (pblock->vtx[0].HasTimestamp())
+ {
+ pblock->vtx[0].SetTxTime(nCoinStakeTime);
+ }
pblock->vtx.push_back(txCoinStake);
}
}
@@ -4493,8 +4570,16 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake)
continue;
// Timestamp limit
- if (tx.nTime > GetAdjustedTime() || (pblock->IsProofOfStake() && tx.nTime > pblock->vtx[1].nTime))
- continue;
+ if (tx.HasTimestamp())
+ {
+ if ( (tx.GetTxTime() > GetAdjustedTime()) ||
+ ( pblock->IsProofOfStake() &&
+ (pblock->vtx[1].HasTimestamp()) &&
+ (tx.GetTxTime() > pblock->vtx[1].GetTxTime()) ) )
+ {
+ continue;
+ }
+ }
// ppcoin: simplify transaction fee - allow free = false
int64 nMinFee = tx.GetMinFee(nBlockSize, false, GMF_BLOCK);
@@ -4571,34 +4656,44 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake)
nLastBlockSize = nBlockSize;
if (fDebug && GetBoolArg("-printpriority"))
- printf("CreateNewBlock(): total size %"PRI64u"\n", nBlockSize);
+ {
+ printf("CreateNewBlock(): total size %" PRI64u "\n", nBlockSize);
+ }
if (pblock->IsProofOfWork())
+ {
pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward((unsigned int) nHeight,
- nFees, pindexPrev->GetBlockHash());
+ nFees, pindexPrev->GetBlockHash());
+ }
// Fill in header
- pblock->hashPrevBlock = pindexPrev->GetBlockHash();
+ pblock->hashPrevBlock = pindexPrev->GetBlockHash();
if (pblock->IsProofOfStake())
- pblock->nTime = pblock->vtx[1].nTime; //same as coinstake timestamp
- pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, pblock->GetMaxTransactionTime());
- if (GetFork(nHeight) >= XST_FORK005)
{
- pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime());
+ pblock->nTime = nCoinStakeTime;
}
- else
+ if (nFork < XST_FORK006)
+ {
+ pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, pblock->GetMaxTransactionTime());
+ }
+ if (nFork < XST_FORK005)
{
pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime() - nMaxClockDrift);
}
+ else
+ {
+ pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetPastTimeLimit()+1);
+ }
if (pblock->IsProofOfWork())
+ {
pblock->UpdateTime(pindexPrev);
- pblock->nNonce = 0;
+ }
+ pblock->nNonce = 0;
}
return pblock.release();
}
-
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
{
// Update nExtraNonce
@@ -4670,10 +4765,10 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
if (hash > hashTarget && pblock->IsProofOfWork())
- return error("BitcoinMiner : proof-of-work not meeting target");
+ return error("CheckWork() : proof-of-work not meeting target");
//// debug print
- printf("BitcoinMiner:\n");
+ printf("CheckWork:\n");
printf("new block found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
pblock->print();
printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
@@ -4682,7 +4777,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
{
LOCK(cs_main);
if (pblock->hashPrevBlock != hashBestChain)
- return error("BitcoinMiner : generated block is stale");
+ return error("CheckWork : generated block is stale");
// Remove key from key pool
reservekey.KeepKey();
@@ -4695,31 +4790,31 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
// Process this block the same as if we had received it from another node
if (!ProcessBlock(NULL, pblock))
- return error("BitcoinMiner : ProcessBlock, block not accepted");
+ return error("CheckWork : ProcessBlock, block not accepted");
}
return true;
}
-void static ThreadBitcoinMiner(void* parg);
+void static ThreadStealthMinter(void* parg);
-static bool fGenerateBitcoins = false;
+static bool fGenerateXST = false;
static bool fLimitProcessors = false;
static int nLimitProcessors = -1;
-void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
+void StealthMinter(CWallet *pwallet, bool fProofOfStake)
{
- printf("CPUMiner started for proof-of-%s\n", fProofOfStake? "stake" : "work");
+ printf("CPUMinter started for proof-of-%s\n", fProofOfStake? "stake" : "work");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
// Make this thread recognisable as the mining thread
- RenameThread("bitcoin-miner");
+ RenameThread("stealth-minter");
// Each thread has its own key and counter
CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0;
- while (fGenerateBitcoins || fProofOfStake)
+ while (fGenerateXST || fProofOfStake)
{
if (fShutdown)
return;
@@ -4730,7 +4825,7 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
Sleep(1000);
if (fShutdown)
return;
- if (!fGenerateBitcoins && !fProofOfStake)
+ if (!fGenerateXST && !fProofOfStake)
return;
}
@@ -4746,7 +4841,11 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
int nHeight = pindexPrev->nHeight + 1;
// int64_t nFees;
- auto_ptr pblock(CreateNewBlock(pwallet, fProofOfStake));
+ #if __cplusplus >= 201103L
+ unique_ptr pblock(CreateNewBlock(pwallet, fProofOfStake));
+ #else
+ auto_ptr pblock(CreateNewBlock(pwallet, fProofOfStake));
+ #endif
if (!pblock.get())
return;
IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce);
@@ -4768,34 +4867,21 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
continue;
}
- printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
+ printf("Running StealthMinter with %" PRIszu " transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
- //
- // Pre-build hash buffers
- //
- //char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
- //char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf);
- //char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf);
-
- //FormatHashBuffers(pblock.get(), pmidstate, pdata, phash1);
-
- //unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
- //unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
-
-
//
// Search
//
int64 nStart = GetTime();
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
- uint256 hash;
+ uint256 hash;
LOOP
{
- hash = pblock->GetHash();
- if (hash <= hashTarget){
- // nHashesDone += pblock->nNonce;
+ hash = pblock->GetHash();
+ if (hash <= hashTarget)
+ {
if (!pblock->SignBlock(*pwalletMain))
break;
@@ -4810,7 +4896,6 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
}
++pblock->nNonce;
-
// Meter hashes/sec
static int64 nHashCounter;
if (nHPSTimerStart == 0)
@@ -4832,7 +4917,7 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
nHPSTimerStart = GetTimeMillis();
nHashCounter = 0;
- printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[THREAD_MINER], dHashesPerSec/1000.0);
+ printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[THREAD_MINTER], dHashesPerSec/1000.0);
}
}
@@ -4841,9 +4926,9 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
// Check for stop or if block needs to be rebuilt
if (fShutdown)
return;
- if (!fGenerateBitcoins)
+ if (!fGenerateXST)
return;
- if (fLimitProcessors && vnThreadsRunning[THREAD_MINER] > nLimitProcessors)
+ if (fLimitProcessors && vnThreadsRunning[THREAD_MINTER] > nLimitProcessors)
return;
if (vNodes.empty())
break;
@@ -4854,60 +4939,66 @@ void BitcoinMiner(CWallet *pwallet, bool fProofOfStake)
if (pindexPrev != pindexBest)
break;
+ int nFork = GetFork(nHeight);
+
// Update nTime every few seconds
- pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, pblock->GetMaxTransactionTime());
- if (GetFork(nHeight) >= XST_FORK005)
+ if (nFork < XST_FORK006)
{
- pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime());
+ pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, pblock->GetMaxTransactionTime());
}
- else
+ if (nFork < XST_FORK005)
{
pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime() - nMaxClockDrift);
}
+ else
+ {
+ pblock->nTime = max(pblock->GetBlockTime(), pindexPrev->GetBlockTime()+1);
+ }
pblock->UpdateTime(pindexPrev);
- if (GetFork(nHeight) >= XST_FORK005)
+ // coinbase timestamp is irrelevant upon XST_FORK006
+ if (nFork < XST_FORK005)
{
- if (pblock->GetBlockTime() >= FutureDrift((int64)pblock->vtx[0].nTime))
+ if (pblock->GetBlockTime() >= (int64)pblock->vtx[0].GetTxTime() + nMaxClockDrift)
break; // need to update coinbase timestamp
}
- else
+ else if (nFork < XST_FORK006)
{
- if (pblock->GetBlockTime() >= (int64)pblock->vtx[0].nTime + nMaxClockDrift)
+ if (pblock->GetBlockTime() >= FutureDrift((int64)pblock->vtx[0].GetTxTime()))
break; // need to update coinbase timestamp
}
}
}
}
-void static ThreadBitcoinMiner(void* parg)
+void static ThreadStealthMinter(void* parg)
{
CWallet* pwallet = (CWallet*)parg;
try
{
- vnThreadsRunning[THREAD_MINER]++;
- BitcoinMiner(pwallet, false);
- vnThreadsRunning[THREAD_MINER]--;
+ vnThreadsRunning[THREAD_MINTER]++;
+ StealthMinter(pwallet, false);
+ vnThreadsRunning[THREAD_MINTER]--;
}
catch (std::exception& e) {
- vnThreadsRunning[THREAD_MINER]--;
- PrintException(&e, "ThreadBitcoinMiner()");
+ vnThreadsRunning[THREAD_MINTER]--;
+ PrintException(&e, "ThreadStealthMinter()");
} catch (...) {
- vnThreadsRunning[THREAD_MINER]--;
- PrintException(NULL, "ThreadBitcoinMiner()");
+ vnThreadsRunning[THREAD_MINTER]--;
+ PrintException(NULL, "ThreadStealthMinter()");
}
nHPSTimerStart = 0;
- if (vnThreadsRunning[THREAD_MINER] == 0)
+ if (vnThreadsRunning[THREAD_MINTER] == 0)
dHashesPerSec = 0;
- printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINER]);
+ printf("ThreadStealthMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
}
-void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
+void GenerateXST(bool fGenerate, CWallet* pwallet)
{
- fGenerateBitcoins = fGenerate;
+ fGenerateXST = fGenerate;
nLimitProcessors = GetArg("-genproclimit", -1);
if (nLimitProcessors == 0)
- fGenerateBitcoins = false;
+ fGenerateXST = false;
fLimitProcessors = (nLimitProcessors != -1);
if (fGenerate)
@@ -4918,12 +5009,12 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
nProcessors = 1;
if (fLimitProcessors && nProcessors > nLimitProcessors)
nProcessors = nLimitProcessors;
- int nAddThreads = nProcessors - vnThreadsRunning[THREAD_MINER];
- printf("Starting %d BitcoinMiner threads\n", nAddThreads);
+ int nAddThreads = nProcessors - vnThreadsRunning[THREAD_MINTER];
+ printf("Starting %d StealthMinter threads\n", nAddThreads);
for (int i = 0; i < nAddThreads; i++)
{
- if (!NewThread(ThreadBitcoinMiner, pwallet))
- printf("Error: NewThread(ThreadBitcoinMiner) failed\n");
+ if (!NewThread(ThreadStealthMinter, pwallet))
+ printf("Error: NewThread(ThreadStealthMinter) failed\n");
Sleep(10);
}
}
diff --git a/src/main.h b/src/main.h
index 0134602..892211f 100644
--- a/src/main.h
+++ b/src/main.h
@@ -45,14 +45,9 @@ static const int64 MIN_RELAY_TX_FEE = 1 * CENT;
static const int64 MAX_MONEY = COIN * 43300000; // 23.3 Million -> 43.3 bumped to be safe
static const int64 CIRCULATION_MONEY = MAX_MONEY;
static const double TAX_PERCENTAGE = 0.00; //no tax
-// 20% annual interest
+// main net: 20% annual interest
static const int64 MAX_STEALTH_PROOF_OF_STAKE = 0.20 * COIN;
-// too many problems with PoW+PoS and big hashes
-// static const unsigned int CUTOFF_POW_BLOCK = 20421;
-static const int CUTOFF_POW_BLOCK = 5460;
-static const unsigned int CUTOFF_POW_TIME = 1405125188;
-// Thu Oct 9 00:00:00 2014 MST
-static const unsigned int STEALTH_ADDR_KICK_IN = 1412834400;
+static const int64 MAX_STEALTH_PROOF_OF_STAKE_TESTNET = 20 * COIN;
static const int64 MIN_TXOUT_AMOUNT = MIN_TX_FEE;
@@ -69,14 +64,15 @@ static const uint256 hashGenesisBlockOfficial(
static const uint256 hashGenesisBlockTestNet (
"0x3dd6302f58a524d7c0bf7a8ee945cab05e2367bed482193eddecbb2a4c3bc634");
-
// cloners: add your new forks higher than highest here
// keep existing
// also, rewrite GetFork
enum ForkNumbers
{
- XST_LAUNCH = 0,
+ XST_GENESIS = 0,
+ XST_FORK004,
XST_FORK005,
+ XST_FORK006,
TOTAL_FORKS
};
@@ -90,6 +86,13 @@ static const int64 nMaxClockDrift = 2 * 60 * 60; // two hours
inline int64 FutureDrift(int64 nTime) {
return fTestNet ? nTime + 7 : nTime + 17; } // up to 17 sec in the future
+inline int GetPoWCutoff()
+{
+ // too many problems with PoW+PoS and big hashes, was block 20421
+ static const int CUTOFF_POW_BLOCK_MNET = 5460;
+ static const int CUTOFF_POW_BLOCK_TNET = 120;
+ return fTestNet ? CUTOFF_POW_BLOCK_TNET : CUTOFF_POW_BLOCK_MNET;
+}
extern CScript COINBASE_FLAGS;
@@ -148,23 +151,24 @@ CBlockIndex* FindBlockByHeight(int nHeight);
bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
bool LoadExternalBlockFile(FILE* fileIn);
-void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
+void GenerateXST(bool fGenerate, CWallet* pwallet);
CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake=false);
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
int64 GetProofOfWorkReward(int nHeight, int64 nFees, uint256 prevHash);
-int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime, int nHeight);
+int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, int nHeight);
unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
unsigned int ComputeMinStake(unsigned int nBase, int64 nTime, unsigned int nBlockTime);
int GetNumBlocksOfPeers();
bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor);
-bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock);
+bool GetTransaction(const uint256 &hash, CTransaction &tx,
+ uint256 &hashBlock, unsigned int &nTimeBlock);
uint256 WantedByOrphan(const CBlock* pblockOrphan);
const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake);
-void BitcoinMiner(CWallet *pwallet, bool fProofOfStake);
+void StealthMinter(CWallet *pwallet, bool fProofOfStake);
void ResendWalletTransactions();
@@ -487,11 +491,14 @@ typedef std::map > MapPrevTx;
*/
class CTransaction
{
+private:
+ unsigned int _nTime;
public:
- static const int CURRENT_VERSION=1;
+ static const int GENESIS_VERSION=1;
+ static const int NOTXTIME_VERSION=2;
+ static const int CURRENT_VERSION=NOTXTIME_VERSION;
int nVersion;
- unsigned int nTime;
std::vector vin;
std::vector vout;
unsigned int nLockTime;
@@ -509,9 +516,9 @@ class CTransaction
(
READWRITE(this->nVersion);
nVersion = this->nVersion;
- if (this->nVersion < 2)
+ if (this->nVersion < CTransaction::NOTXTIME_VERSION)
{
- READWRITE(nTime);
+ READWRITE(_nTime);
}
READWRITE(vin);
READWRITE(vout);
@@ -520,8 +527,15 @@ class CTransaction
void SetNull()
{
- nVersion = CTransaction::CURRENT_VERSION;
- nTime = GetAdjustedTime();
+ if (GetFork(nBestHeight) < XST_FORK006)
+ {
+ nVersion = CTransaction::GENESIS_VERSION;
+ }
+ else
+ {
+ nVersion = CTransaction::CURRENT_VERSION;
+ }
+ _nTime = GetAdjustedTime();
vin.clear();
vout.clear();
nLockTime = 0;
@@ -533,9 +547,26 @@ class CTransaction
return (vin.empty() && vout.empty());
}
+ // upon XST_FORK006 txid hash does not include signatures
+ // this allows the tx hash to be signed,
+ // making the txid immutable without invalidating sigs
uint256 GetHash() const
{
- return SerializeHash(*this);
+ // mining software expects filled coinbase script sigs
+ if (HasTimestamp() || IsCoinBase())
+ {
+ return SerializeHash(*this);
+ }
+ else
+ {
+ CTransaction txTmp(*this);
+ // Blank the sigs
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ {
+ txTmp.vin[i].scriptSig = CScript();
+ }
+ return SerializeHash(txTmp);
+ }
}
bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const
@@ -689,13 +720,57 @@ class CTransaction
return true;
}
+ bool HasTimestamp() const
+ {
+ return (nVersion < CTransaction::NOTXTIME_VERSION);
+ }
+
+ unsigned int GetTxTime() const
+ {
+ return _nTime;
+ }
+
+ void SetTxTime(unsigned int nNewTime)
+ {
+ _nTime = nNewTime;
+ }
+
+ void AdjustTime(int nAdjustment)
+ {
+ // take care not to wrap an unsigned int
+ if (nAdjustment < 0)
+ {
+ if (-nAdjustment >= (int)_nTime)
+ {
+ _nTime = 0;
+ }
+ else
+ {
+ _nTime += nAdjustment;
+ }
+ }
+ // sanity check
+ else if (nAdjustment <= (int)_nTime)
+ {
+ _nTime += nAdjustment;
+ }
+ else
+ {
+ _nTime += _nTime;
+ }
+ }
+
friend bool operator==(const CTransaction& a, const CTransaction& b)
{
- return (a.nVersion == b.nVersion &&
- a.nTime == b.nTime &&
- a.vin == b.vin &&
- a.vout == b.vout &&
- a.nLockTime == b.nLockTime);
+ if (a.HasTimestamp() && b.HasTimestamp() &&
+ (a.GetTxTime() != b.GetTxTime()))
+ {
+ return false;
+ }
+ return (a.nVersion == b.nVersion &&
+ a.vin == b.vin &&
+ a.vout == b.vout &&
+ a.nLockTime == b.nLockTime);
}
friend bool operator!=(const CTransaction& a, const CTransaction& b)
@@ -714,9 +789,9 @@ class CTransaction
{
std::string str;
str += IsCoinBase()? "Coinbase" : (IsCoinStake()? "Coinstake" : "CTransaction");
- str += strprintf("(hash=%s, nTime=%d, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%d)\n",
+ str += strprintf("(hash=%s, nTime=%d, ver=%d, vin.size=%" PRIszu ", vout.size=%" PRIszu ", nLockTime=%d)\n",
GetHash().ToString().substr(0,10).c_str(),
- nTime,
+ _nTime,
nVersion,
vin.size(),
vout.size(),
@@ -772,7 +847,8 @@ class CTransaction
bool ClientConnectInputs();
bool CheckTransaction() const;
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
- bool GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const; // ppcoin: get transaction coin age
+ // ppcoin: get transaction coin age
+ bool GetCoinAge(CTxDB& txdb, unsigned int nBlockTime, uint64& nCoinAge) const;
protected:
const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
@@ -1017,7 +1093,15 @@ class CBlock
std::pair GetProofOfStake() const
{
- return IsProofOfStake()? std::make_pair(vtx[1].vin[0].prevout, vtx[1].nTime) : std::make_pair(COutPoint(), (unsigned int)0);
+ if (IsProofOfStake())
+ {
+ unsigned int nTxTime = vtx[1].HasTimestamp() ? vtx[1].GetTxTime() : nTime;
+ return std::make_pair(vtx[1].vin[0].prevout, nTxTime);
+ }
+ else
+ {
+ return std::make_pair(COutPoint(), (unsigned int)0);
+ }
}
// ppcoin: get max transaction timestamp
@@ -1025,7 +1109,17 @@ class CBlock
{
int64 maxTransactionTime = 0;
BOOST_FOREACH(const CTransaction& tx, vtx)
- maxTransactionTime = std::max(maxTransactionTime, (int64)tx.nTime);
+ {
+ if (tx.HasTimestamp())
+ {
+ maxTransactionTime = std::max(maxTransactionTime,
+ (int64)tx.GetTxTime());
+ }
+ }
+ if ((maxTransactionTime == 0) && ((vtx.size() > 0)))
+ {
+ maxTransactionTime = nTime;
+ }
return maxTransactionTime;
}
@@ -1136,7 +1230,7 @@ class CBlock
void print() const
{
- printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu", vchBlockSig=%s)\n",
+ printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%" PRIszu ", vchBlockSig=%s)\n",
GetHash().ToString().c_str(),
nVersion,
hashPrevBlock.ToString().c_str(),
@@ -1265,7 +1359,14 @@ class CBlockIndex
{
SetProofOfStake();
prevoutStake = block.vtx[1].vin[0].prevout;
- nStakeTime = block.vtx[1].nTime;
+ if (block.vtx[1].HasTimestamp())
+ {
+ nStakeTime = block.vtx[1].GetTxTime();
+ }
+ else
+ {
+ nStakeTime = nTime;
+ }
}
else
{
@@ -1405,7 +1506,7 @@ class CBlockIndex
std::string ToString() const
{
- return strprintf("CBlockIndex(nprev=%p, pnext=%p, nFile=%u, nBlockPos=%-6d nHeight=%d, nMint=%s, nMoneySupply=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016"PRI64x", nStakeModifierChecksum=%08x, hashProofOfStake=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)",
+ return strprintf("CBlockIndex(nprev=%p, pnext=%p, nFile=%u, nBlockPos=%-6d nHeight=%d, nMint=%s, nMoneySupply=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016" PRI64x ", nStakeModifierChecksum=%08x, hashProofOfStake=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)",
pprev, pnext, nFile, nBlockPos, nHeight,
FormatMoney(nMint).c_str(), FormatMoney(nMoneySupply).c_str(),
GeneratedStakeModifier() ? "MOD" : "-", GetStakeEntropyBit(), IsProofOfStake()? "PoS" : "PoW",
diff --git a/src/net.cpp b/src/net.cpp
index e56c593..48c194c 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -509,7 +509,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64 nTimeout)
if (fDebug) {
printf("ConnectNode(): pszDest: %s\n", pszDest);
}
-
+
/// debug print
printf("trying connection %s lastseen=%.1fhrs\n",
@@ -802,8 +802,8 @@ void ThreadSocketHandler2(void* parg)
vNodesUnsecure.push_back(pnode);
}
}
- if (
- 0 > 2 * secured - 3 * unsecured
+ if (// don't remove unsecure nodes if no secure nodes
+ (secured > 0) && (0 > 2 * secured - 3 * unsecured)
) {
random_shuffle(vNodesUnsecure.begin(), vNodesUnsecure.end(), GetRandInt);
printf("removing unsecured connection %s\n", (*vNodesUnsecure.begin())->addr.ToString().c_str());
@@ -894,8 +894,10 @@ void ThreadSocketHandler2(void* parg)
int nInbound = 0;
if (hSocket != INVALID_SOCKET)
+ {
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
printf("Warning: Unknown socket family\n");
+ }
{
LOCK(cs_vNodes);
@@ -914,6 +916,7 @@ void ThreadSocketHandler2(void* parg)
{
{
LOCK(cs_setservAddNodeAddresses);
+ printf("max connections reached\n");
if (!setservAddNodeAddresses.count(addr))
closesocket(hSocket);
}
@@ -961,7 +964,7 @@ void ThreadSocketHandler2(void* parg)
if (nPos > ReceiveBufferSize()) {
if (!pnode->fDisconnect)
- printf("socket recv flood control disconnect (%"PRIszu" bytes)\n", vRecv.size());
+ printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
pnode->CloseSocketDisconnect();
}
else {
@@ -1268,7 +1271,7 @@ void DumpAddresses()
CAddrDB adb;
adb.Write(addrman);
- printf("Flushed %d addresses to peers.dat %"PRI64d"ms\n",
+ printf("Flushed %d addresses to peers.dat %" PRI64d "ms\n",
addrman.size(), GetTimeMillis() - nStart);
}
@@ -1347,7 +1350,7 @@ void static ThreadStakeMinter(void* parg)
try
{
vnThreadsRunning[THREAD_STEALTHER]++;
- BitcoinMiner(pwallet, true);
+ StealthMinter(pwallet, true);
vnThreadsRunning[THREAD_STEALTHER]--;
}
catch (std::exception& e) {
@@ -1926,7 +1929,7 @@ void StartNode(void* parg)
}
// Generate coins in the background
- GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
+ GenerateXST(GetBoolArg("-gen", false), pwalletMain);
}
@@ -1954,7 +1957,7 @@ bool StopNode()
if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
- if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
+ if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStealthMinter still running\n");
if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
#ifdef USE_UPNP
diff --git a/src/net.h b/src/net.h
index 3181763..3fc13cf 100644
--- a/src/net.h
+++ b/src/net.h
@@ -100,7 +100,7 @@ enum threadId
THREAD_SOCKETHANDLER,
THREAD_OPENCONNECTIONS,
THREAD_MESSAGEHANDLER,
- THREAD_MINER,
+ THREAD_MINTER,
THREAD_RPCLISTENER,
THREAD_UPNP,
THREAD_DNSSEED,
@@ -330,7 +330,7 @@ class CNode
// the key is the earliest time the request can be sent
int64& nRequestTime = mapAlreadyAskedFor[inv];
if (fDebugNet)
- printf("askfor %s %"PRI64d" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
+ printf("askfor %s %" PRI64d " (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
// Make sure not to reuse time indexes to keep things in the same order
int64 nNow = (GetTime() - 1) * 1000000;
diff --git a/src/onionseed.h b/src/onionseed.h
index 6c0e1df..d66ec62 100644
--- a/src/onionseed.h
+++ b/src/onionseed.h
@@ -17,6 +17,7 @@ static const char *strMainNetOnionSeed[][1] = {
};
static const char *strTestNetOnionSeed[][1] = {
+ // {"cbakvnfjvpb7hfxe.onion"},
{NULL}
};
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index a75d105..3b7e8bf 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -922,7 +922,8 @@ void BitcoinGUI::unlockWalletForTxn() {
return;
}
// Unlock wallet when requested by wallet model
- if((walletModel->getEncryptionStatus() == WalletModel::Locked) || fWalletUnlockMintOnly)
+ if ((walletModel->getEncryptionStatus() == WalletModel::Locked) ||
+ fWalletUnlockMintOnly)
{
AskPassphraseDialog::Mode mode = AskPassphraseDialog::UnlockTxn;
AskPassphraseDialog dlg(mode, this);
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index efdba55..b789e6b 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -680,7 +680,7 @@ void CoinControlDialog::updateView()
itemOutput->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(out.tx->vout[out.i].nValue), 15, " ")); // padding so that sorting works correctly
// date
- itemOutput->setText(COLUMN_DATE, QDateTime::fromTime_t(out.tx->GetTxTime()).toUTC().toString("yy-MM-dd hh:mm"));
+ itemOutput->setText(COLUMN_DATE, QDateTime::fromTime_t(out.tx->GetWTxTime()).toUTC().toString("yy-MM-dd hh:mm"));
// immature PoS reward
if (out.tx->IsCoinStake() && out.tx->GetBlocksToMaturity() > 0 && out.tx->GetDepthInMainChain() > 0) {
diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp
index e0f69ed..575f0a8 100644
--- a/src/qt/editaddressdialog.cpp
+++ b/src/qt/editaddressdialog.cpp
@@ -25,9 +25,12 @@ EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) :
setWindowTitle(tr("New receiving address"));
ui->addressEdit->setEnabled(false);
ui->addressEdit->setVisible(false);
- if(fTestNet || (pindexBest->nTime >= STEALTH_ADDR_KICK_IN)){
+ if (GetFork(pindexBest->nHeight) >= XST_FORK004)
+ {
ui->stealthCB->setEnabled(true);
- }else{
+ }
+ else
+ {
ui->stealthCB->setEnabled(false);
}
ui->stealthCB->setVisible(true);
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index a434102..a07cb3b 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -40,7 +40,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
strHTML.reserve(4000);
strHTML += "";
- int64 nTime = wtx.GetTxTime();
+ int64 nTime = wtx.GetWTxTime();
int64 nCredit = wtx.GetCredit();
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index ecd7353..b6f1b22 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -25,7 +25,7 @@ bool TransactionRecord::showTransaction(const CWalletTx &wtx)
QList TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
{
QList parts;
- int64 nTime = wtx.GetTxTime();
+ int64 nTime = wtx.GetWTxTime();
int64 nCredit = wtx.GetCredit(true);
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index ec677a7..552a758 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -240,9 +240,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListIsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": "")));
result.push_back(Pair("proofhash", blockindex->IsProofOfStake()? blockindex->hashProofOfStake.GetHex() : blockindex->GetBlockHash().GetHex()));
result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
- result.push_back(Pair("modifier", strprintf("%016"PRI64x, blockindex->nStakeModifier)));
+ result.push_back(Pair("modifier", strprintf("%016" PRI64x, blockindex->nStakeModifier)));
result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum)));
Array txinfo;
BOOST_FOREACH (const CTransaction& tx, block.vtx)
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 602ff2e..46a1599 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -45,7 +45,7 @@ Value setgenerate(const Array& params, bool fHelp)
}
mapArgs["-gen"] = (fGenerate ? "1" : "0");
- GenerateBitcoins(fGenerate, pwalletMain);
+ GenerateXST(fGenerate, pwalletMain);
return Value::null;
}
@@ -434,11 +434,14 @@ Value getblocktemplate(const Array& params, bool fHelp)
static CBlockIndex* pindexPrev;
static int64 nStart;
static CBlock* pblock;
+ int64 nTxTime = pblock->vtx[0].HasTimestamp() ?
+ (int64) pblock->vtx[0].GetTxTime() :
+ (int64) pblock->GetBlockTime();
if ((pindexPrev != pindexBest) ||
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5) ||
((GetFork(pindexBest->nHeight + 1) >= XST_FORK005) &&
// give it 12 seconds for a new getwork (because future drift is only 15 s)
- (pblock->GetBlockTime() >= FutureDrift((int64)pblock->vtx[0].nTime) + 12)))
+ (pblock->GetBlockTime() >= FutureDrift(nTxTime) + 12)))
{
// Clear pindexPrev so future calls make a new block, despite any failures from here on
pindexPrev = NULL;
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 49b99eb..6021e45 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -63,7 +63,7 @@ Value getpeerinfo(const Array& params, bool fHelp)
Object obj;
obj.push_back(Pair("addr", stats.addrName));
- obj.push_back(Pair("services", strprintf("%08"PRI64x, stats.nServices)));
+ obj.push_back(Pair("services", strprintf("%08" PRI64x, stats.nServices)));
obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend));
obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv));
obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 3379395..73336c3 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -54,7 +54,10 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
{
entry.push_back(Pair("txid", tx.GetHash().GetHex()));
entry.push_back(Pair("version", tx.nVersion));
- entry.push_back(Pair("time", (boost::int64_t)tx.nTime));
+ if (tx.HasTimestamp())
+ {
+ entry.push_back(Pair("time", (boost::int64_t)tx.GetTxTime()));
+ }
entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
Array vin;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
@@ -127,7 +130,8 @@ Value getrawtransaction(const Array& params, bool fHelp)
CTransaction tx;
uint256 hashBlock = 0;
- if (!GetTransaction(hash, tx, hashBlock))
+ unsigned int nTimeBlock;
+ if (!GetTransaction(hash, tx, hashBlock, nTimeBlock))
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
@@ -504,7 +508,13 @@ string sendtoaddresswithtime(string sAddress, int64 nAmount, unsigned int nTime)
throw JSONRPCError(-101, "Send amount too small");
CWalletTx wtx;
- wtx.nTime = nTime;
+
+ if (!wtx.HasTimestamp())
+ {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Transactions no longer have timestamps.");
+ }
+
+ wtx.SetTxTime(nTime);
if (pwalletMain->IsLocked())
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED,
@@ -574,13 +584,22 @@ Value decryptsend(const Array& params, bool fHelp)
return string("<>");
}
+ // StealthText is going to be unsupported upon FORK006
+ // because replay prevention relies on timestamps for uids.
+ // If there seems to be demand, I will work out replay attacks
+ // probably by including a uid in OP_RETURN.
+ if (GetFork(nBestHeight) >= XST_FORK006)
+ {
+ return string("<>");
+ }
+
// look for existing matching timestamps in wallet (ghetto uid)
// should handle replay with scriptsig in future (version 2)
LOCK(pwalletMain->cs_wallet);
for (map::const_iterator it = pwalletMain->mapWallet.begin();
it != pwalletMain->mapWallet.end(); ++it) {
const CWalletTx* pcoin = &(*it).second;
- if (pcoin->nTime == nTime) {
+ if (pcoin->GetTxTime() == nTime) {
return string("<>");
}
}
@@ -616,7 +635,8 @@ Value sendrawtransaction(const Array& params, bool fHelp)
// or in the memory pool:
CTransaction existingTx;
uint256 hashBlock = 0;
- if (GetTransaction(hashTx, existingTx, hashBlock))
+ unsigned int nTimeBlock;
+ if (GetTransaction(hashTx, existingTx, hashBlock, nTimeBlock))
{
if (hashBlock != 0)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index c9c3546..8d3ac52 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -40,14 +40,16 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair("confirmations", confirms));
if (wtx.IsCoinBase() || wtx.IsCoinStake())
entry.push_back(Pair("generated", true));
+ unsigned int nBlockTime = 0;
if (confirms > 0)
{
+ nBlockTime = mapBlockIndex[wtx.hashBlock]->nTime;
entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
entry.push_back(Pair("blockindex", wtx.nIndex));
- entry.push_back(Pair("blocktime", (boost::int64_t)(mapBlockIndex[wtx.hashBlock]->nTime)));
+ entry.push_back(Pair("blocktime", (boost::int64_t)(nBlockTime)));
}
entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
- entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
+ entry.push_back(Pair("time", (boost::int64_t)wtx.GetWTxTime()));
entry.push_back(Pair("timereceived", (boost::int64_t)wtx.nTimeReceived));
BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
entry.push_back(Pair(item.first, item.second));
@@ -792,7 +794,7 @@ Value addmultisigaddress(const Array& params, bool fHelp)
if ((int)keys.size() < nRequired)
throw runtime_error(
strprintf("not enough keys supplied "
- "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired));
+ "(got %" PRIszu " keys, but need at least %d to redeem)", keys.size(), nRequired));
std::vector pubkeys;
pubkeys.resize(keys.size());
for (unsigned int i = 0; i < keys.size(); i++)
@@ -1012,34 +1014,14 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
bool fAllAccounts = (strAccount == string("*"));
- // Generated blocks assigned to account ""
- if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
- {
- Object entry;
- entry.push_back(Pair("account", string("")));
- if (nGeneratedImmature)
- {
- entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
- entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
- }
- else
- {
- entry.push_back(Pair("category", "generate"));
- entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
- }
- if (fLong)
- WalletTxToJSON(wtx, entry);
- ret.push_back(entry);
- }
-
// Sent
- if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
+ if ((!wtx.IsCoinStake()) && (!listSent.empty() || nFee != 0) &&
+ (fAllAccounts || strAccount == strSentAccount))
{
BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& s, listSent)
{
Object entry;
entry.push_back(Pair("account", strSentAccount));
- //entry.push_back(Pair("address", CBitcoinAddress(s.first).ToString()));
MaybePushAddress(entry, s.first);
entry.push_back(Pair("category", "send"));
entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
@@ -1053,6 +1035,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
{
+ bool stop = false;
BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64)& r, listReceived)
{
string account;
@@ -1062,8 +1045,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
{
Object entry;
entry.push_back(Pair("account", account));
- entry.push_back(Pair("address", CBitcoinAddress(r.first).ToString()));
- if (wtx.IsCoinBase())
+ MaybePushAddress(entry, r.first);
+ if (wtx.IsCoinBase() || wtx.IsCoinStake())
{
if (wtx.GetDepthInMainChain() < 1)
entry.push_back(Pair("category", "orphan"));
@@ -1073,12 +1056,22 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
entry.push_back(Pair("category", "generate"));
}
else
+ {
entry.push_back(Pair("category", "receive"));
- entry.push_back(Pair("amount", ValueFromAmount(r.second)));
+ }
+ if (!wtx.IsCoinStake())
+ entry.push_back(Pair("amount", ValueFromAmount(r.second)));
+ else
+ {
+ entry.push_back(Pair("amount", ValueFromAmount(-nFee)));
+ stop = true; // only one coinstake output
+ }
if (fLong)
WalletTxToJSON(wtx, entry);
ret.push_back(entry);
}
+ if (stop)
+ break;
}
}
}
@@ -1320,7 +1313,8 @@ Value gettransaction(const Array& params, bool fHelp)
{
CTransaction tx;
uint256 hashBlock = 0;
- if (GetTransaction(hash, tx, hashBlock))
+ unsigned int nTimeBlock;
+ if (GetTransaction(hash, tx, hashBlock, nTimeBlock))
{
entry.push_back(Pair("txid", hash.GetHex()));
TxToJSON(tx, 0, entry);
@@ -1336,7 +1330,10 @@ Value gettransaction(const Array& params, bool fHelp)
if (pindex->IsInMainChain())
{
entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
- entry.push_back(Pair("txntime", (boost::int64_t)tx.nTime));
+ if (tx.HasTimestamp())
+ {
+ entry.push_back(Pair("txntime", (boost::int64_t)tx.GetTxTime()));
+ }
entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
}
else
diff --git a/src/tor/adapter/toradapter.cpp b/src/tor/adapter/toradapter.cpp
index 430f8ee..948c66b 100644
--- a/src/tor/adapter/toradapter.cpp
+++ b/src/tor/adapter/toradapter.cpp
@@ -43,7 +43,11 @@ int check_interrupted(
static boost::mutex initializing;
+#if __cplusplus >= 201103L
+static std::unique_ptr > uninitialized(
+#else
static std::auto_ptr > uninitialized(
+#endif
new boost::unique_lock(
initializing
)
diff --git a/src/txdb-leveldb.cpp b/src/txdb-leveldb.cpp
index 9fd9418..6dccd73 100644
--- a/src/txdb-leveldb.cpp
+++ b/src/txdb-leveldb.cpp
@@ -406,7 +406,7 @@ bool CTxDB::LoadBlockIndex()
// NovaCoin: calculate stake modifier checksum
pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex);
if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum))
- return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindex->nHeight, pindex->nStakeModifier);
+ return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016" PRI64x, pindex->nHeight, pindex->nStakeModifier);
}
// Load hashBestChain pointer to end of best chain
diff --git a/src/util.cpp b/src/util.cpp
index 5d58333..c7b8e38 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -373,7 +373,7 @@ string FormatMoney(int64 n, bool fPlus)
int64 n_abs = (n > 0 ? n : -n);
int64 quotient = n_abs/COIN;
int64 remainder = n_abs%COIN;
- string str = strprintf("%"PRI64d".%06"PRI64d, quotient, remainder);
+ string str = strprintf("%" PRI64d ".%06" PRI64d, quotient, remainder);
// Right-trim excess zeros before the decimal point:
int nTrim = 0;
@@ -1123,7 +1123,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
path = GetDefaultDataDir();
}
if (fNetSpecific && GetBoolArg("-testnet", false))
- path /= "testnet2";
+ path /= "testnet";
fs::create_directory(path);
@@ -1278,7 +1278,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime)
// Add data
vTimeOffsets.input(nOffsetSample);
- printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
+ printf("Added time data, samples %d, offset %+" PRI64d " (%+" PRI64d " minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
{
int64 nMedian = vTimeOffsets.median();
@@ -1313,10 +1313,10 @@ void AddTimeData(const CNetAddr& ip, int64 nTime)
}
if (fDebug) {
BOOST_FOREACH(int64 n, vSorted)
- printf("%+"PRI64d" ", n);
+ printf("%+" PRI64d " ", n);
printf("| ");
}
- printf("nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
+ printf("nTimeOffset = %+" PRI64d " (%+" PRI64d " minutes)\n", nTimeOffset, nTimeOffset/60);
}
}
diff --git a/src/util.h b/src/util.h
index dcbbae2..a108b6e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -248,7 +248,7 @@ void runCommand(std::string strCommand);
inline std::string i64tostr(int64 n)
{
- return strprintf("%"PRI64d, n);
+ return strprintf("%" PRI64d, n);
}
inline std::string itostr(int n)
diff --git a/src/version.h b/src/version.h
index ffe4feb..9ad3599 100644
--- a/src/version.h
+++ b/src/version.h
@@ -24,23 +24,31 @@ extern const std::string CLIENT_DATE;
// display version
#define DISPLAY_VERSION_MAJOR 2
-#define DISPLAY_VERSION_MINOR 1
+#define DISPLAY_VERSION_MINOR 2
#define DISPLAY_VERSION_REVISION 0
-#define DISPLAY_VERSION_BUILD 4
+#define DISPLAY_VERSION_BUILD 0
//
// network protocol versioning
//
-// 62009 : New alerts with easier clearing
-// Different keys for alerts and hash sync checkpoints
-// 62010 : New rule to accept duplicate stake on bootstrap (only!)
-// Technically not a network protocol difference
-// 62020 : Fixes signature malleability
-// 62100 : Clockdrift improvements & Checklocktimeverify (forking)
-// Client version: 2.1.0
+// 61001 : [Genesis]
+// 61011 : fork 1
+// 1.0.1.1 : Fix PoS difficulty adjustment during PoW period
+// 61021 : fork 2
+// 1.0.2.1 : Kill PoW at 5460 to deal with forks on pools
+// 61040 : fork 3
+// 1.0.4.0 : Adjust max bits computation for 60s block times
+// 61300 : fork 4
+// 1.3.0.0 : Stealth Addresses
+// 62100 : fork 5
+// 2.1.0.0 : Clockdrift improvements & Checklocktimeverify (forking)
+// 2.1.0.1 : SignSignature fix
// 2.1.0.4 : OpenSSL v1.1 compatibility
-static const int PROTOCOL_VERSION = 62100;
+// 62200 : fork 6
+// 2.2.0.0 : Removing all traces of tx timestamp
+// Immaleable transaction IDs
+static const int PROTOCOL_VERSION = 62200;
// intial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 61300;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index e5257a5..93fceb1 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -116,7 +116,7 @@ bool CWallet::LoadCScript(const CScript &redeemScript)
{
if(redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE){
std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString();
- printf("%s: Warning: This wallet contains a redeemScript of size %"PRIszu" which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
+ printf("%s: Warning: This wallet contains a redeemScript of size %" PRIszu " which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
__func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr.c_str());
return true;
}
@@ -704,12 +704,35 @@ bool CWallet::IsChange(const CTxOut& txout) const
return false;
}
-int64 CWalletTx::GetTxTime() const
+int64 CWalletTx::GetWTxTime() const
{
int64 n = nTimeSmart;
return n ? n : nTimeReceived;
}
+// FIXME: optimization - set timestamp of CWalletTx when updated with blockindex
+unsigned int CWalletTx::GetTxTime() const
+{
+ if (HasTimestamp())
+ {
+ return CTransaction::GetTxTime();
+ }
+
+ map::iterator mi = mapBlockIndex.find(hashBlock);
+ if (mi == mapBlockIndex.end())
+ {
+ if (fDebug)
+ {
+ printf("CWalletTx::GetTxTime(): block not found: %s\n",
+ hashBlock.ToString().c_str());
+ }
+ // not in a block yet, give an earliest possible time
+ return pindexBest->nTime + 1;
+ }
+ CBlockIndex* pindex = (*mi).second;
+ return pindex->nTime;
+}
+
int CWalletTx::GetRequestCount() const
{
// Returns -1 if it wasn't being tracked
@@ -769,14 +792,13 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
BOOST_FOREACH(const CTxOut& txout, vout)
{
if (txout.scriptPubKey.empty())
- continue;
+ continue;
bool fIsMine;
if (nDebit > 0)
{
- // Don't report 'change' txouts
- //if (nDebit > 0 && pwallet->IsChange(txout))
- if (pwallet->IsChange(txout))
+ // Don't report 'change' txouts
+ if (pwallet->IsChange(txout) && !IsCoinStake())
continue;
fIsMine = pwallet->IsMine(txout);
}
@@ -795,8 +817,8 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l
listSent.push_back(make_pair(address, txout.nValue));
if (fIsMine)
- listReceived.push_back(make_pair(address, txout.nValue));
- }
+ listReceived.push_back(make_pair(address, txout.nValue));
+ }
}
void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGeneratedImmature, int64& nGeneratedMature, int64& nReceived,
@@ -913,7 +935,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
LOCK(cs_wallet);
while (pindex)
{
- if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey -7200))){
+ if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))){
pindex = pindex->pnext;
continue;
}
@@ -961,7 +983,7 @@ void CWallet::ReacceptWalletTransactions()
// Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
if (txindex.vSpent.size() != wtx.vout.size())
{
- printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %"PRIszu" != wtx.vout.size() %"PRIszu"\n", txindex.vSpent.size(), wtx.vout.size());
+ printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %" PRIszu " != wtx.vout.size() %" PRIszu "\n", txindex.vSpent.size(), wtx.vout.size());
continue;
}
for (unsigned int i = 0; i < txindex.vSpent.size(); i++)
@@ -1256,12 +1278,19 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, in
const CWalletTx *pcoin = output.tx;
if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
+ {
continue;
+ }
int i = output.i;
- if (pcoin->nTime > nSpendTime)
- continue; // ppcoin: timestamp must not exceed spend time
+ // ppcoin: timestamp must not exceed spend time
+ // if a tx doesn't have timestamp, then there is no way to set
+ // it in the future, so ignore this test
+ if (pcoin->HasTimestamp() && pcoin->GetTxTime() > nSpendTime)
+ {
+ continue;
+ }
int64 n = pcoin->vout[i].nValue;
@@ -1372,11 +1401,12 @@ void CWallet::AvailableCoinsForStaking(vector& vCoins, unsigned int nSp
{
const CWalletTx* pcoin = &(*it).second;
- // Filtering by tx timestamp instead of block timestamp may give false positives but never false negatives
- if (pcoin->nTime + nStakeMinAge > nSpendTime)
+ if (pcoin->GetBlocksToMaturity() > 0)
continue;
- if (pcoin->GetBlocksToMaturity() > 0)
+ // Filtering by tx timestamp instead of block timestamp
+ // may give false positives but never false negatives
+ if ((pcoin->GetTxTime() + nStakeMinAge) > nSpendTime)
continue;
int nDepth = pcoin->GetDepthInMainChain();
@@ -1466,8 +1496,12 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW
// Choose coins to use
set > setCoins;
int64 nValueIn = 0;
- if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn, coinControl))
+ int nSpendTime = wtxNew.HasTimestamp() ? wtxNew.GetTxTime() : ::GetAdjustedTime();
+ if (!SelectCoins(nTotalValue, nSpendTime, setCoins, nValueIn, coinControl))
+ {
+ printf("CreateTransaction(): could not select coins\n");
return false;
+ }
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
@@ -1520,12 +1554,16 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
if (SignSignature(*this, *coin.first, wtxNew, nIn++) != 0)
{
+ printf("CreateTransaction(): could not sign tx\n");
return false;
}
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
+ {
+ printf("CreateTransaction(): too many bytes\n");
return false;
+ }
dPriority /= nBytes;
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
@@ -2005,9 +2043,9 @@ bool CWallet::SendStealthMoneyToDestination(CStealthAddress& sxAddress, int64 nV
if (fDebug)
{
- printf("Stealth send to generated pubkey %"PRIszu": %s\n", pkSendTo.size(), HexStr(pkSendTo).c_str());
+ printf("Stealth send to generated pubkey %" PRIszu ": %s\n", pkSendTo.size(), HexStr(pkSendTo).c_str());
printf("hash %s\n", addrTo.ToString().c_str());
- printf("ephem_pubkey %"PRIszu": %s\n", ephem_pubkey.size(), HexStr(ephem_pubkey).c_str());
+ printf("ephem_pubkey %" PRIszu ": %s\n", ephem_pubkey.size(), HexStr(ephem_pubkey).c_str());
};
std::vector vchNarr;
@@ -2138,7 +2176,7 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar
printf("StealthSecret failed.\n");
continue;
};
- //printf("pkExtracted %"PRIszu": %s\n", pkExtracted.size(), HexStr(pkExtracted).c_str());
+ //printf("pkExtracted %" PRIszu ": %s\n", pkExtracted.size(), HexStr(pkExtracted).c_str());
CPubKey cpkE(pkExtracted);
@@ -2274,7 +2312,7 @@ bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint
int64 nReserveBalance = 0;
if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance))
- return error("CreateCoinStake : invalid reserve balance amount");
+ return error("GetStakeWeight : invalid reserve balance amount");
if (nBalance <= nReserveBalance)
return false;
@@ -2298,7 +2336,7 @@ bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint
continue;
}
- int64 nTimeWeight = GetWeight((int64)pcoin.first->nTime, (int64)GetTime());
+ int64 nTimeWeight = GetWeight((int64)pcoin.first->GetTxTime(), (int64)GetTime());
CBigNum bnCoinDayWeight = CBigNum(pcoin.first->vout[pcoin.second].nValue) * nTimeWeight / COIN / (24 * 60 * 60);
// Weight is greater than zero
@@ -2323,7 +2361,9 @@ bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint
return true;
}
-bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew)
+bool CWallet::CreateCoinStake(const CKeyStore& keystore,unsigned int nBits,
+ int64 nSearchInterval, CTransaction& txNew,
+ unsigned int &nCoinStakeTime)
{
CBlockIndex* pindexPrev = pindexBest;
CBigNum bnTargetPerCoinDay;
@@ -2346,7 +2386,11 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
set > setCoins;
vector vwtxPrev;
int64 nValueIn = 0;
- if (!SelectCoins(nBalance - nReserveBalance, txNew.nTime, setCoins, nValueIn))
+ // upon XST_FORK006, CTransactions do not have dependable timestamps,
+ // however for the data structure timestamp can be used temporarily
+ // for now CTransaction timestamp inits as the adjusted time
+ if (!SelectCoins(nBalance - nReserveBalance,
+ nCoinStakeTime, setCoins, nValueIn))
return false;
if (setCoins.empty())
@@ -2374,7 +2418,10 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
static int nMaxStakeSearchInterval = 60;
- if (block.GetBlockTime() + nStakeMinAge > txNew.nTime - nMaxStakeSearchInterval)
+ // upon XST_FORK006, CTransactions do not have dependable timestamps,
+ // however for the data structure timestamp can be used temporarily
+ // for now CTransaction timestamp inits as the adjusted time
+ if (block.GetBlockTime() + nStakeMinAge > nCoinStakeTime - nMaxStakeSearchInterval)
continue; // only count coins meeting min age requirement
bool fKernelFound = false;
@@ -2385,7 +2432,13 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
// Search nSearchInterval seconds back up to nMaxStakeSearchInterval
uint256 hashProofOfStake = 0;
COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
- if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake))
+ if (CheckStakeKernelHash(nBits,
+ block,
+ txindex.pos.nTxPos - txindex.pos.nBlockPos,
+ *pcoin.first,
+ prevoutStake,
+ nCoinStakeTime - n, // re timestamps, see above
+ hashProofOfStake))
{
// Found a kernel
if (fDebug && GetBoolArg("-printcoinstake"))
@@ -2440,16 +2493,23 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
scriptPubKeyOut = scriptPubKeyKernel;
}
- txNew.nTime -= n;
+ nCoinStakeTime -= n;
+ if (txNew.HasTimestamp())
+ {
+ txNew.AdjustTime(-n);
+ }
txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
nCredit += pcoin.first->vout[pcoin.second].nValue;
- // printf(">> Wallet: CreateCoinStake: nCredit = %"PRI64d"\n", nCredit);
+ // printf(">> Wallet: CreateCoinStake: nCredit = %" PRI64d "\n", nCredit);
vwtxPrev.push_back(pcoin.first);
txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
- if (GetWeight(block.GetBlockTime(), (int64_t)txNew.nTime) < nStakeSplitAge)
+ // upon XST_FORK006, CTransactions do not have dependable timestamps,
+ // however for the data structure timestamp can be used temporarily
+ // for now CTransaction timestamp inits as the adjusted time
+ if (GetWeight(block.GetBlockTime(), (int64_t)nCoinStakeTime) < nStakeSplitAge)
txNew.vout.push_back(CTxOut(0, scriptPubKeyOut)); //split stake
if (fDebug && GetBoolArg("-printcoinstake"))
@@ -2463,7 +2523,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
}
if (nCredit == 0 || nCredit > nBalance - nReserveBalance)
{
- // printf(">> Wallet: CreateCoinStake: nCredit = %"PRI64d", nBalance = %"PRI64d", nReserveBalance = %"PRI64d"\n", nCredit, nBalance, nReserveBalance);
+ // printf(">> Wallet: CreateCoinStake: nCredit = %" PRI64d ", nBalance = %" PRI64d ", nReserveBalance = %" PRI64d "\n", nCredit, nBalance, nReserveBalance);
return false;
}
@@ -2474,7 +2534,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
if (txNew.vout.size() == 2 && ((pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey))
&& pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
{
- int64_t nTimeWeight = GetWeight((int64_t)pcoin.first->nTime, (int64_t)txNew.nTime);
+ int64_t nTimeWeight = GetWeight((int64_t)pcoin.first->GetTxTime(), nCoinStakeTime);
// Stop adding more inputs if already too many inputs
if (txNew.vin.size() >= 100)
break;
@@ -2501,9 +2561,10 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int
CTxDB txdb("r");
const CBlockIndex* pIndex0 = GetLastBlockIndex(pindexBest, false);
- if (!txNew.GetCoinAge(txdb, nCoinAge))
+ // nCoinStakeTime will be block time after FORK006
+ if (!txNew.GetCoinAge(txdb, nCoinStakeTime, nCoinAge))
return error("CreateCoinStake : failed to calculate coin age");
- int64 nReward = GetProofOfStakeReward(nCoinAge, nBits, txNew.nTime, pIndex0->nHeight);
+ int64 nReward = GetProofOfStakeReward(nCoinAge, nBits, pIndex0->nHeight);
if (nReward <= 0) {
return false;
}
@@ -2739,12 +2800,12 @@ void CWallet::PrintWallet(const CBlock& block)
if (block.IsProofOfWork() && mapWallet.count(block.vtx[0].GetHash()))
{
CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
- printf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
+ printf(" mine: %d %d %" PRI64d "", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
}
if (block.IsProofOfStake() && mapWallet.count(block.vtx[1].GetHash()))
{
CWalletTx& wtx = mapWallet[block.vtx[1].GetHash()];
- printf(" stake: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
+ printf(" stake: %d %d %" PRI64d "", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
}
}
@@ -2807,7 +2868,7 @@ bool CWallet::NewKeyPool()
walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
setKeyPool.insert(nIndex);
}
- printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
+ printf("CWallet::NewKeyPool wrote %" PRI64d " new keys\n", nKeys);
}
return true;
}
@@ -2837,7 +2898,7 @@ bool CWallet::TopUpKeyPool(unsigned int nSize)
if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
throw runtime_error("TopUpKeyPool() : writing generated key failed");
setKeyPool.insert(nEnd);
- printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
+ printf("keypool added key %" PRI64d ", size=%" PRIszu "\n", nEnd, setKeyPool.size());
}
}
return true;
@@ -2867,7 +2928,7 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
assert(keypool.vchPubKey.IsValid());
if (fDebug && GetBoolArg("-printkeypool"))
- printf("keypool reserve %"PRI64d"\n", nIndex);
+ printf("keypool reserve %" PRI64d "\n", nIndex);
}
}
@@ -2895,7 +2956,7 @@ void CWallet::KeepKey(int64 nIndex)
walletdb.ErasePool(nIndex);
}
if(fDebug)
- printf("keypool keep %"PRI64d"\n", nIndex);
+ printf("keypool keep %" PRI64d "\n", nIndex);
}
void CWallet::ReturnKey(int64 nIndex)
@@ -2906,7 +2967,7 @@ void CWallet::ReturnKey(int64 nIndex)
setKeyPool.insert(nIndex);
}
//if(fDebug)
- //printf("keypool return %"PRI64d"\n", nIndex);
+ //printf("keypool return %" PRI64d "\n", nIndex);
}
bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
diff --git a/src/wallet.h b/src/wallet.h
index 0c56605..3a0b466 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -196,7 +196,9 @@ class CWallet : public CCryptoKeyStore
int64 GetNewMint() const;
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
bool GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint64& nMaxWeight, uint64& nWeight);
- bool CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew);
+ bool CreateCoinStake(const CKeyStore& keystore,unsigned int nBits,
+ int64 nSearchInterval, CTransaction& txNew,
+ unsigned int &nCoinStakeTime);
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
std::string SendMoneyToDestination(const CTxDestination &address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
@@ -702,7 +704,9 @@ class CWalletTx : public CMerkleTx
bool WriteToDisk();
- int64 GetTxTime() const;
+ unsigned int GetTxTime() const;
+
+ int64 GetWTxTime() const;
int GetRequestCount() const;
void AddSupportingTransactions(CTxDB& txdb);
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 61c92c0..88cd5bd 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -256,7 +256,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
//// debug print
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
- //printf(" %12"PRI64d" %s %s %s\n",
+ //printf(" %12" PRI64d " %s %s %s\n",
// wtx.vout[0].nValue,
// DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(),
// wtx.hashBlock.ToString().substr(0,20).c_str(),
@@ -608,7 +608,7 @@ void ThreadFlushWalletDB(void* parg)
bitdb.CheckpointLSN(strFile);
bitdb.mapFileUseCount.erase(mi++);
- printf("Flushed wallet.dat %"PRI64d"ms\n", GetTimeMillis() - nStart);
+ printf("Flushed wallet.dat %" PRI64d "ms\n", GetTimeMillis() - nStart);
}
}
}
@@ -669,7 +669,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
// Set -rescan so any missing transactions will be
// found.
int64 now = GetTime();
- std::string newFilename = strprintf("wallet.%"PRI64d".bak", now);
+ std::string newFilename = strprintf("wallet.%" PRI64d ".bak", now);
int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL,
newFilename.c_str(), DB_AUTO_COMMIT);
@@ -688,7 +688,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys)
printf("Salvage(aggressive) found no records in %s.\n", newFilename.c_str());
return false;
}
- printf("Salvage(aggressive) found %"PRIszu" records\n", salvagedData.size());
+ printf("Salvage(aggressive) found %" PRIszu " records\n", salvagedData.size());
bool fSuccess = allOK;
Db* pdbCopy = new Db(&dbenv.dbenv, 0);