@@ -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 ());
0 comments on commit
9bbc395