0

In PoS coins there is a common 'time to stake' estimate, this is based on the users own accumulated stake amount as a proportion of the network wide stake weight.

However there is no way for any node to reliably estimate the network stake weight, in theory it's just all nodes individual weights added together, but as no single node is guaranteed to see all others without duplication, I wanted to understand how this is calculated.

2

While I don't know how other PoS blockchains operate, I can give some insight about the PoSv2/3 version based on Peercoin's implementation of proof of stake; one such example would be Novacoin.

The total network weight is ~computed by this function:

double GetPoSKernelPS()
{
    int nPoSInterval = 72;
    double dStakeKernelsTriedAvg = 0;
    int nStakesHandled = 0, nStakesTime = 0;

    CBlockIndex* pindex = pindexBest;;
    CBlockIndex* pindexPrevStake = NULL;

    while (pindex && nStakesHandled < nPoSInterval)
    {
        if (pindex->IsProofOfStake())
        {
            dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296.0;
            nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0;
            pindexPrevStake = pindex;
            nStakesHandled++;
        }

        pindex = pindex->pprev;
    }

    if (!nStakesHandled)
        return 0;

    return dStakeKernelsTriedAvg / nStakesTime;
}

How the weight estimation algorithm works is pretty interesting: it iterates backwards through the blockchain, from the latest known best block until it finds 72 blocks that were produced using a proof of stake (basically all the past 72 blocks).

Using these 72 PoS blocks, it calculates the total amount of time that has passed between each consecutive block pair (added up to a total -- nStakesTime) and the total amount of "difficulty" that was satisfied during the production of those blocks (dStakeKernelsTriedAvg).

The final network weight estimation is given by dividing the "amount of work" by the "amount of time".

This algorithm does not attempt to calculate the exact amount of coins that are being "at stake" at any given time, because as you noticed that wouldn't be possible; yet the estimations it gives are pretty accurate.

0

Novacoins implementation of GetPoSKernelPS() does a splendid job to calculate the effective network staking weight. Someone wondering about the 4294967296.0 constant, see here: https://en.bitcoin.it/wiki/Difficulty#What_is_the_formula_for_difficulty.3F

However the value returned by GetPoSKernelPS() when used for staking reward time estimation does distort the result during times when the network weight is changing. This is because the chance to win a stake is solely dependent on the current difficulty and adjusting the difficulty, depending on the projects parameters, takes days.

This is why for Spectrecoins staking reward time estimation we use the following code (simplified):

double GetPoSKernelPS()
{
    double result = 0;
    if (nNodeMode == NT_THIN)
    {
        if (pindexBestHeader->IsProofOfStake())
            result = GetHeaderDifficulty(pindexBestHeader) * 4294967296.0;
    }
    else
    {
        if (pindexBest->IsProofOfStake())
            result = GetDifficulty(pindexBest) * 4294967296.0;
    }

    if (result > 0)
        result /= TARGET_BLOCK_TIME;

    if (Params().IsProtocolV2(nBestHeight))
        result *= STAKE_TIMESTAMP_MASK + 1;

    return result;
}

uint64_t nWeight = pwalletMain->GetStakeWeight() + pwalletMain->GetSpectreStakeWeight();    
uint64_t nNetworkWeight = GetPoSKernelPS();
uint64_t nExpectedTime = TARGET_BLOCK_TIME * nNetworkWeight / nWeight) 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.