Permalink
Browse files

1.5 Hard Fork

On Saturday Jan 17 2015:
Fix Max weight to be correctly set to 30 days
Set Past/Future Drift to 5 min
Set Max PoS Reward to 250

At block 1,600,000:
Sanity Check Spacing
  • Loading branch information...
Tranz5 committed Nov 11, 2014
1 parent b5f2fce commit d677d58eb5f1fb7d0f07df7b10ede8bb832a8890
Showing with 133 additions and 25 deletions.
  1. +6 −15 src/kernel.cpp
  2. +102 −4 src/main.cpp
  3. +23 −3 src/main.h
  4. +2 −3 src/wallet.cpp
View
@@ -22,7 +22,6 @@ static std::map<int, unsigned int> mapStakeModifierCheckpoints =
;
// Get time weight
int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd)
{
// Kernel hash weight starts from 0 at the 10-day min age
@@ -31,11 +30,10 @@ int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd)
//
// Maximum TimeWeight is 30 days.
// Tranz We are going to want to change this to fix the max weight. Requires a hard fork
// New Code:
// return min(nIntervalEnd - nIntervalBeginning - nStakeMinAge, (int64_t)nStakeMaxAge);
return min(nIntervalEnd - nIntervalBeginning, (int64_t)nStakeMaxAge) - nStakeMinAge;
if ( nIntervalEnd > VERSION1_5_SWITCH_TIME )
return min(nIntervalEnd - nIntervalBeginning - nStakeMinAge, (int64_t)nStakeMaxAge);
else
return min(nIntervalEnd - nIntervalBeginning, (int64_t)nStakeMaxAge) - nStakeMinAge;
}
// Get the last stake modifier and its generation time from a given block
@@ -282,19 +280,12 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, unsigned
CBigNum bnTargetPerCoinDay;
bnTargetPerCoinDay.SetCompact(nBits);
int64_t nValueIn = txPrev.vout[prevout.n].nValue;
uint256 hashBlockFrom = blockFrom.GetHash();
// v0.3 protocol kernel hash weight starts from 0 at the 10-day min age
// this change increases active coins participating the hash and helps
// to secure the network when proof-of-stake difficulty is low
// Tranz We are going to want to change this to fix the max weight. Requires a hard fork
// New Code:
// int64_t nTimeWeight = min((int64_t)nTimeTx - txPrev.nTime - nStakeMinAge, (int64_t)nStakeMaxAge);
int64_t nTimeWeight = min((int64_t)nTimeTx - txPrev.nTime, (int64_t)nStakeMaxAge) - nStakeMinAge;
CBigNum bnCoinDayWeight = CBigNum(nValueIn) * nTimeWeight / COIN / (24 * 60 * 60);
CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)txPrev.nTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60);
targetProofOfStake = CBigNum(bnCoinDayWeight * bnTargetPerCoinDay).getuint256();
// Calculate hash
CDataStream ss(SER_GETHASH, 0);
uint64_t nStakeModifier = 0;
View
@@ -1084,6 +1084,18 @@ int64_t GetProofOfWorkReward()
// miner's coin stake reward based on nBits and coin age spent (coin-days)
int64_t GetProofOfStakeReward(int64_t nCoinAge, unsigned int nBits, unsigned int nTime, bool bCoinYearOnly)
{
int64_t nSubsidy = 0;
if ( nTime > VERSION1_5_SWITCH_TIME )
nSubsidy = GetProofOfStakeRewardV2(nCoinAge, nBits, nTime, bCoinYearOnly);
else
nSubsidy = GetProofOfStakeRewardV1(nCoinAge, nBits, nTime, bCoinYearOnly);
return nSubsidy;
}
int64_t GetProofOfStakeRewardV1(int64_t nCoinAge, unsigned int nBits, unsigned int nTime, bool bCoinYearOnly)
{
int64_t nRewardCoinYear;
@@ -1175,6 +1187,54 @@ int64_t GetProofOfStakeReward(int64_t nCoinAge, unsigned int nBits, unsigned int
return nSubsidy;
}
int64_t GetProofOfStakeRewardV2(int64_t nCoinAge, unsigned int nBits, unsigned int nTime, bool bCoinYearOnly)
{
CBigNum bnRewardCoinYearLimit = MAX_MINT_PROOF_OF_STAKE_FIX2; // Base stake mint rate, 100% year interest
int64_t nRewardCoinYearLimit = MAX_MINT_PROOF_OF_STAKE_FIX2;
CBigNum bnTarget;
bnTarget.SetCompact(nBits);
CBigNum bnTargetLimit = bnProofOfStakeLimit;
bnTargetLimit.SetCompact(bnTargetLimit.GetCompact());
int64_t nSubsidyLimit = 250 * COIN;
// HoboNickels: reward for coin-year is cut in half every 64x multiply of PoS difficulty
// A reasonably continuous curve is used to avoid shock to market
// (bnRewardCoinYearLimit / nRewardCoinYear) ** 4 == bnProofOfStakeLimit / bnTarget
//
// Human readable form:
//
// nRewardCoinYear = 1 / (posdiff ^ 1/4)
CBigNum bnLowerBound = 10 * CENT; // Lower interest bound is 10% per year
CBigNum bnUpperBound = bnRewardCoinYearLimit;
while (bnLowerBound + CENT <= bnUpperBound)
{
CBigNum bnMidValue = (bnLowerBound + bnUpperBound) / 2;
LogPrint("creation", "GetProofOfStakeReward() : lower=%d upper=%d mid=%d\n", bnLowerBound.getuint64(), bnUpperBound.getuint64(), bnMidValue.getuint64());
if (bnMidValue * bnMidValue * bnMidValue * bnMidValue * bnTargetLimit > bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnRewardCoinYearLimit * bnTarget)
bnUpperBound = bnMidValue;
else
bnLowerBound = bnMidValue;
}
int64_t nRewardCoinYear = bnUpperBound.getuint64();
nRewardCoinYear = min((nRewardCoinYear / CENT) * CENT, nRewardCoinYearLimit);
if(bCoinYearOnly)
return nRewardCoinYear;
int64_t nSubsidy = (nCoinAge * 33 * nRewardCoinYear) / (365 * 33 + 8);
LogPrint("creation","GetProofOfStakeReward(): create=%s nCoinAge=%d nBits=%d, Amount Truncated %s\n", FormatMoney(nSubsidy), nCoinAge, nBits, nSubsidyLimit < nSubsidy ? FormatMoney(nSubsidy - nSubsidyLimit) : FormatMoney(0));
nSubsidy = min(nSubsidy, nSubsidyLimit);
return nSubsidy;
}
static const int64_t nTargetTimespan = 0.16 * 24 * 60 * 60; // 4-hour
static const int64_t nTargetSpacingWorkMax = 12 * nStakeTargetSpacing; // 2-hour
@@ -1223,6 +1283,14 @@ const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfSta
}
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
if (pindexLast->nHeight + 1 > VERSION1_5_SWITCH_BLOCK)
return GetNextTargetRequiredV2(pindexLast, fProofOfStake);
else
return GetNextTargetRequiredV1(pindexLast, fProofOfStake);
}
unsigned int GetNextTargetRequiredV1(const CBlockIndex* pindexLast, bool fProofOfStake)
{
CBigNum bnTargetLimit = !fProofOfStake ? bnProofOfWorkLimit : bnProofOfStakeLimit;
@@ -1252,10 +1320,6 @@ unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfS
int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();
// Tranz saved for later.
// int nHeight = pindexPrev->nHeight+1;
// if (nHeight >= ???? & nActualSpacing < 0) nActualSpacing = 0; //Sanity Check on nActualSpacing, corrects negative block values
// ppcoin: target change every block
// ppcoin: retarget with exponential moving toward target spacing
CBigNum bnNew;
@@ -1271,6 +1335,39 @@ unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfS
return bnNew.GetCompact();
}
unsigned int GetNextTargetRequiredV2(const CBlockIndex* pindexLast, bool fProofOfStake)
{
CBigNum bnTargetLimit = !fProofOfStake ? bnProofOfWorkLimit : bnProofOfStakeLimit;
if (pindexLast == NULL)
return bnTargetLimit.GetCompact(); // genesis block
const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
if (pindexPrev->pprev == NULL)
return bnTargetLimit.GetCompact(); // first block
const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
if (pindexPrevPrev->pprev == NULL)
return bnTargetLimit.GetCompact(); // second block
int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();
int64_t nTargetSpacing = fProofOfStake? nStakeTargetSpacing : min(nTargetSpacingWorkMax, (int64_t) nStakeTargetSpacing * (1 + pindexLast->nHeight - pindexPrev->nHeight));
if (nActualSpacing < 0)
nActualSpacing = nTargetSpacing;
CBigNum bnNew;
bnNew.SetCompact(pindexPrev->nBits);
int64_t nInterval = nTargetTimespan / nTargetSpacing;
bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
bnNew /= ((nInterval + 1) * nTargetSpacing);
if (bnNew > bnTargetLimit)
bnNew = bnTargetLimit;
return bnNew.GetCompact();
}
bool CheckProofOfWork(uint256 hash, unsigned int nBits)
{
CBigNum bnTarget;
@@ -1287,6 +1384,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
return true;
}
// Return maximum amount of blocks that other nodes claim to have
int GetNumBlocksOfPeers()
{
View
@@ -60,12 +60,14 @@ static const int64_t MAX_SPLIT_AMOUNT = 20 * COIN;
static const int64_t MAX_COMBINE_AMOUNT = MAX_SPLIT_AMOUNT * 2;
/** Hard Fork Change Times */
/** Hard Fork Change Times/Block */
static const unsigned int PROTOCOL_SWITCH_TIME = 1371686400; // 20 Jun 2013 00:00:00
static const unsigned int REWARD_SWITCH_TIME = 1369432800; // 25 May 2013 00:00:00
static const unsigned int POS_REWARD_SWITCH_TIME = 1378684800; // 9 SEP 2013 00:00:00
static const unsigned int POS_REWARD_FIX_TIME = 1383177600; // 31 OCT 2013 00:00:00
static const unsigned int POS_REWARD_FIX_TIME2 = 1383606000; // 04 Nov 2013 23:00:00
static const unsigned int VERSION1_5_SWITCH_TIME = 1421489410; // Sat, 17 Jan 2015 10:10:10 GMT
static const unsigned int VERSION1_5_SWITCH_BLOCK = 1600000; // Block 1.6 million, approx same time
inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
@@ -75,8 +77,21 @@ static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20
static const uint256 hashGenesisBlockOfficial("0x000009ea5ef5019446b315e7e581fc2ea184315ed46c9ddeadc8aa9442deedc9");
static const uint256 hashGenesisBlockTestNet("0x0000f9e0292f278190e4d58cd1e1e9a32b7466c8092bd2371ffc80b06f8eca4a");
inline int64_t PastDrift(int64_t nTime) { return nTime - 2 * 60 * 60; } // up to 2 hours from the past
inline int64_t FutureDrift(int64_t nTime) { return nTime + 2 * 60 * 60; } // up to 2 hours from the future
inline int64_t PastDrift(int64_t nTime)
{
if (nTime > VERSION1_5_SWITCH_TIME)
return nTime - 5 * 60; // up to 5 minutes from the past
else
return nTime - 2 * 60 * 60; // up to 120 minutes from the past
}
inline int64_t FutureDrift(int64_t nTime)
{
if (nTime > VERSION1_5_SWITCH_TIME)
return nTime + 5 * 60; // up to 5 minutes from the future
else
return nTime + 2 * 60 * 60; // up to 120 minutes from the future
}
extern CScript COINBASE_FLAGS;
@@ -151,8 +166,13 @@ bool LoadExternalBlockFile(FILE* fileIn);
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake);
unsigned int GetNextTargetRequiredV1(const CBlockIndex* pindexLast, bool fProofOfStake);
unsigned int GetNextTargetRequiredV2(const CBlockIndex* pindexLast, bool fProofOfStake);
int64_t GetProofOfWorkReward();
int64_t GetProofOfStakeReward(int64_t nCoinAge, unsigned int nBits, unsigned int nTime ,bool bCoinYearOnly=false);
int64_t GetProofOfStakeRewardV1(int64_t nCoinAge, unsigned int nBits, unsigned int nTime ,bool bCoinYearOnly=false);
int64_t GetProofOfStakeRewardV2(int64_t nCoinAge, unsigned int nBits, unsigned int nTime ,bool bCoinYearOnly=false);
unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime);
unsigned int ComputeMinStake(unsigned int nBase, int64_t nTime, unsigned int nBlockTime);
View
@@ -1568,14 +1568,13 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
bool CWallet::GetStakeWeightFromValue(const int64_t& nTime, const int64_t& nValue, uint64_t& nWeight)
{
// This is a negative value when there is no weight. But set it to zero
// so the user is not confused. Used in reporting in Coin Control.
// Descisions based on this function should be used with care.
int64_t nTimeWeight = GetWeight(nTime, (int64_t)GetTime());
if (nTimeWeight < 0 )
nTimeWeight=0;
nTimeWeight=0;
CBigNum bnCoinDayWeight = CBigNum(nValue) * nTimeWeight / COIN / (24 * 60 * 60);
nWeight = bnCoinDayWeight.getuint64();

0 comments on commit d677d58

Please sign in to comment.