Permalink
Browse files

Peercoin: v0.5 protocol adjustment

Allow transaction output value to be 0.
Use dynamic stake modifier for kernel generation
Protocol switch schedule:
Testnet switch - Nov 16, 2015
Mainnet switch - Mar 15, 2016
  • Loading branch information...
sunnyking committed Sep 11, 2015
1 parent 57b8c8d commit 9bbc395388f7aee75930bc78eb65cff8fa47cd23
Showing with 129 additions and 14 deletions.
  1. +10 −0 src/db.cpp
  2. +2 −0 src/db.h
  3. +73 −5 src/kernel.cpp
  4. +5 −1 src/kernel.h
  5. +38 −7 src/main.cpp
  6. +1 −1 src/version.h
View
@@ -529,6 +529,16 @@ bool CTxDB::WriteV04UpgradeTime(const unsigned int& nUpgradeTime)
return Write(string("nProtocolV04UpgradeTime"), nUpgradeTime);
}
+bool CTxDB::ReadV05UpgradeTime(unsigned int& nUpgradeTime)
+{
+ return Read(string("nProtocolV05UpgradeTime"), nUpgradeTime);
+}
+
+bool CTxDB::WriteV05UpgradeTime(const unsigned int& nUpgradeTime)
+{
+ return Write(string("nProtocolV05UpgradeTime"), nUpgradeTime);
+}
+
CBlockIndex static * InsertBlockIndex(uint256 hash)
{
if (hash == 0)
View
@@ -302,6 +302,8 @@ class CTxDB : public CDB
bool WriteCheckpointPubKey(const std::string& strPubKey);
bool ReadV04UpgradeTime(unsigned int& nUpgradeTime);
bool WriteV04UpgradeTime(const unsigned int& nUpgradeTime);
+ bool ReadV05UpgradeTime(unsigned int& nUpgradeTime);
+ bool WriteV05UpgradeTime(const unsigned int& nUpgradeTime);
bool LoadBlockIndex();
};
View
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2013 The PPCoin developers
+// Copyright (c) 2012-2015 The Peercoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,13 +15,24 @@ unsigned int nProtocolV03TestSwitchTime = 1359781000;
// Protocol switch time of v0.4 kernel protocol
unsigned int nProtocolV04SwitchTime = 1399300000;
unsigned int nProtocolV04TestSwitchTime = 1395700000;
+// Protocol switch time of v0.5 kernel protocol
+unsigned int nProtocolV05SwitchTime = 1458000000;
+unsigned int nProtocolV05TestSwitchTime = 1447700000;
+
// TxDB upgrade time for v0.4 protocol
// Note: v0.4 upgrade does not require block chain re-download. However,
// user must upgrade before the protocol switch deadline, otherwise
// re-download of blockchain is required. The timestamp of upgrade
// is recorded in transaction database to alert user of the requirement.
unsigned int nProtocolV04UpgradeTime = 0;
+// TxDB upgrade time for v0.5 protocol
+// Note: v0.5 upgrade does not require block chain re-download. However,
+// user must upgrade before the protocol switch deadline, otherwise
+// re-download of blockchain is required. The timestamp of upgrade
+// is recorded in transaction database to alert user of the requirement.
+unsigned int nProtocolV05UpgradeTime = 0;
+
// Modifier interval: time to elapse before new modifier is computed
// Set to 6-hour for production network and 20-minute for test network
unsigned int nModifierInterval = MODIFIER_INTERVAL;
@@ -47,6 +58,12 @@ bool IsProtocolV04(unsigned int nTimeBlock)
return (nTimeBlock >= (fTestNet? nProtocolV04TestSwitchTime : nProtocolV04SwitchTime));
}
+// Whether the given transaction is subject to new v0.5 protocol
+bool IsProtocolV05(unsigned int nTimeTx)
+{
+ return (nTimeTx >= (fTestNet? nProtocolV05TestSwitchTime : nProtocolV05SwitchTime));
+}
+
// Get the last stake modifier and its generation time from a given block
static bool GetLastStakeModifier(const CBlockIndex* pindex, uint64& nStakeModifier, int64& nModifierTime)
{
@@ -253,9 +270,48 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64& nStakeMo
return true;
}
-// The stake modifier used to hash for a stake kernel is chosen as the stake
+// V0.5: Stake modifier used to hash for a stake kernel is chosen as the stake
+// modifier that is (nStakeMinAge minus a selection interval) earlier than the
+// stake, thus at least a selection interval later than the coin generating the // kernel, as the generating coin is from at least nStakeMinAge ago.
+static bool GetKernelStakeModifierV05(unsigned int nTimeTx, uint64& nStakeModifier, int& nStakeModifierHeight, int64& nStakeModifierTime, bool fPrintProofOfStake)
+{
+ const CBlockIndex* pindex = pindexBest;
+ nStakeModifierHeight = pindex->nHeight;
+ nStakeModifierTime = pindex->GetBlockTime();
+ int64 nStakeModifierSelectionInterval = GetStakeModifierSelectionInterval();
+
+ if (nStakeModifierTime + nStakeMinAge - nStakeModifierSelectionInterval <= (int64) nTimeTx)
+ {
+ // Best block is still more than
+ // (nStakeMinAge minus a selection interval) older than kernel timestamp
+ if (fPrintProofOfStake)
+ return error("GetKernelStakeModifier() : best block %s at height %d too old for stake",
+ pindex->GetBlockHash().ToString().c_str(), pindex->nHeight);
+ else
+ return false;
+ }
+ // loop to find the stake modifier earlier by
+ // (nStakeMinAge minus a selection interval)
+ while (nStakeModifierTime + nStakeMinAge - nStakeModifierSelectionInterval >(int64) nTimeTx)
+ {
+ if (!pindex->pprev)
+ { // reached genesis block; should not happen
+ return error("GetKernelStakeModifier() : reached genesis block");
+ }
+ pindex = pindex->pprev;
+ if (pindex->GeneratedStakeModifier())
+ {
+ nStakeModifierHeight = pindex->nHeight;
+ nStakeModifierTime = pindex->GetBlockTime();
+ }
+ }
+ nStakeModifier = pindex->nStakeModifier;
+ return true;
+}
+
+// V0.3: Stake modifier used to hash for a stake kernel is chosen as the stake
// modifier about a selection interval later than the coin generating the kernel
-static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier, int& nStakeModifierHeight, int64& nStakeModifierTime, bool fPrintProofOfStake)
+static bool GetKernelStakeModifierV03(uint256 hashBlockFrom, uint64& nStakeModifier, int& nStakeModifierHeight, int64& nStakeModifierTime, bool fPrintProofOfStake)
{
nStakeModifier = 0;
if (!mapBlockIndex.count(hashBlockFrom))
@@ -287,6 +343,15 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier
return true;
}
+// Get the stake modifier specified by the protocol to hash for a stake kernel
+static bool GetKernelStakeModifier(uint256 hashBlockFrom, unsigned int nTimeTx, uint64& nStakeModifier, int& nStakeModifierHeight, int64& nStakeModifierTime, bool fPrintProofOfStake)
+{
+ if (IsProtocolV05(nTimeTx))
+ return GetKernelStakeModifierV05(nTimeTx, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake);
+ else
+ return GetKernelStakeModifierV03(hashBlockFrom, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake);
+}
+
// ppcoin kernel protocol
// coinstake must meet hash target according to the protocol:
// kernel (input 0) must meet the formula
@@ -295,6 +360,9 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64& nStakeModifier
// amount of coin age one owns.
// The reason this hash is chosen is the following:
// nStakeModifier:
+// (v0.5) uses dynamic stake modifier around 21 days before the kernel,
+// versus static stake modifier about 9 days after the staked
+// coin (txPrev) used in v0.3
// (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
@@ -334,7 +402,7 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
int64 nStakeModifierTime = 0;
if (IsProtocolV03(nTimeTx)) // v0.3 protocol
{
- if (!GetKernelStakeModifier(blockFrom.GetHash(), nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake))
+ if (!GetKernelStakeModifier(blockFrom.GetHash(), nTimeTx, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake))
return false;
ss << nStakeModifier;
}
@@ -354,7 +422,7 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
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",
- IsProtocolV03(nTimeTx)? "0.3" : "0.2",
+ IsProtocolV05(nTimeTx)? "0.5" : (IsProtocolV03(nTimeTx)? "0.3" : "0.2"),
IsProtocolV03(nTimeTx)? nStakeModifier : (uint64) nBits,
nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx,
hashProofOfStake.ToString().c_str());
View
@@ -1,4 +1,4 @@
-// Copyright (c) 2012-2013 The PPCoin developers
+// Copyright (c) 2012-2015 The Peercoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef PPCOIN_KERNEL_H
@@ -19,11 +19,15 @@ extern unsigned int nProtocolV03SwitchTime;
extern unsigned int nProtocolV03TestSwitchTime;
// TxDB upgrade time for v0.4 protocol
extern unsigned int nProtocolV04UpgradeTime;
+// TxDB Upgrade time for v0.5 protocol
+extern unsigned int nProtocolV05UpgradeTime;
// Whether a given coinstake is subject to new v0.3 protocol
bool IsProtocolV03(unsigned int nTimeCoinStake);
// Whether a given block is subject to new v0.4 protocol
bool IsProtocolV04(unsigned int nTimeBlock);
+// Whether a given transaction is subject to new v0.5 protocol
+bool IsProtocolV05(unsigned int nTimeTx);
// Compute the hash modifier for proof-of-stake
bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64& nStakeModifier, bool& fGeneratedStakeModifier);
View
@@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
-// Copyright (c) 2011-2013 The PPCoin developers
+// Copyright (c) 2011-2015 The Peercoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -481,7 +481,9 @@ bool CTransaction::CheckTransaction() const
if (txout.IsEmpty() && (!IsCoinBase()) && (!IsCoinStake()))
return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction"));
// ppcoin: enforce minimum output amount
- if ((!txout.IsEmpty()) && txout.nValue < MIN_TXOUT_AMOUNT)
+ // v0.5 protocol: zero amount allowed
+ if ((!txout.IsEmpty()) && txout.nValue < MIN_TXOUT_AMOUNT &&
+ !(IsProtocolV05(nTime) && (txout.nValue == 0)))
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue below minimum"));
if (txout.nValue > MAX_MONEY)
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
@@ -2372,7 +2374,9 @@ bool LoadBlockIndex(bool fAllowNew)
CTxDB txdb;
if (!txdb.WriteV04UpgradeTime(0))
return error("LoadBlockIndex() : failed to init upgrade info");
- printf(" Upgrade Info: v0.4+ txdb initialization\n");
+ if (!txdb.WriteV05UpgradeTime(0))
+ return error("LoadBlockIndex() : failed to init upgrade info");
+ printf(" Upgrade Info: v0.5+ txdb initialization\n");
txdb.Close();
}
}
@@ -2401,20 +2405,39 @@ bool LoadBlockIndex(bool fAllowNew)
if (txdb.ReadV04UpgradeTime(nProtocolV04UpgradeTime))
{
if (nProtocolV04UpgradeTime)
- printf(" Upgrade Info: txdb upgrade to v0.4 detected at timestamp %d\n", nProtocolV04UpgradeTime);
+ printf(" Upgrade Info: txdb upgrade v0.3->v0.4 detected at timestamp %d\n", nProtocolV04UpgradeTime);
else
- printf(" Upgrade Info: v0.4+ no txdb upgrade detected.\n");
+ printf(" Upgrade Info: no txdb upgrade v0.3->v0.4 detected.\n");
}
else
{
nProtocolV04UpgradeTime = GetTime();
- printf(" Upgrade Info: upgrading txdb from v0.3 at timestamp %u\n", nProtocolV04UpgradeTime);
+ printf(" Upgrade Info: upgrading txdb from v0.3->v0.5 at timestamp %u\n", nProtocolV04UpgradeTime);
if (!txdb.WriteV04UpgradeTime(nProtocolV04UpgradeTime))
return error("LoadBlockIndex() : failed to write upgrade info");
}
txdb.Close();
}
+ {
+ CTxDB txdb;
+ if (txdb.ReadV05UpgradeTime(nProtocolV05UpgradeTime))
+ {
+ if (nProtocolV05UpgradeTime)
+ printf(" Upgrade Info: txdb upgrade to v0.5 detected at timestamp %d\n", nProtocolV05UpgradeTime);
+ else
+ printf(" Upgrade Info: v0.5+ no txdb upgrade detected.\n");
+ }
+ else
+ {
+ nProtocolV05UpgradeTime = GetTime();
+ printf(" Upgrade Info: upgrading txdb to v0.5 at timestamp %u\n", nProtocolV05UpgradeTime);
+ if (!txdb.WriteV05UpgradeTime(nProtocolV05UpgradeTime))
+ return error("LoadBlockIndex() : failed to write upgrade info");
+ }
+ txdb.Close();
+ }
+
return true;
}
@@ -2556,7 +2579,15 @@ string GetWarnings(string strFor)
if (IsProtocolV04(nProtocolV04UpgradeTime + 60*60*24)) // 1 day margin
{
nPriority = 5000;
- strStatusBar = strRPC = "WARNING: Blockchain redownload required approaching or past v0.4 upgrade deadline.";
+ strStatusBar = strRPC = "WARNING: Blockchain redownload required upgrading from pre v0.4 wallet.";
+ }
+ else if (IsProtocolV05(nProtocolV05UpgradeTime + 60*60*24)) // 1 day margin
+ {
+ // v0.5 protocol does not change modifier computation from v0.4.
+ // So redownload of blockchain is not required for late upgrades,
+ // but still recommended.
+ nPriority = 200;
+ strStatusBar = strRPC = "WARNING: Blockchain redownload recommended approaching or past v0.5 upgrade deadline.";
}
// Alerts
View
@@ -43,7 +43,7 @@ static const int PPCOIN_VERSION =
// network protocol versioning
//
-static const int PROTOCOL_VERSION = 60004;
+static const int PROTOCOL_VERSION = 60005;
// earlier versions not supported as of Feb 2012, and are disconnected
// NOTE: as of bitcoin v0.6 message serialization (vSend, vRecv) still

0 comments on commit 9bbc395

Please sign in to comment.