Skip to content

Commit

Permalink
1.5 Hard Fork
Browse files Browse the repository at this point in the history
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 d677d58
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 25 deletions.
21 changes: 6 additions & 15 deletions src/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down
106 changes: 102 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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()
{
Expand Down
26 changes: 23 additions & 3 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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); }
Expand All @@ -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;

Expand Down Expand Up @@ -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);

Expand Down
5 changes: 2 additions & 3 deletions src/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit d677d58

Please sign in to comment.