Skip to content
158 changes: 157 additions & 1 deletion src/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <chain.h>
#include "chainparams.h"

/**
* CChain implementation
Expand Down Expand Up @@ -118,7 +119,79 @@ void CBlockIndex::BuildSkip()
pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}

arith_uint256 GetBlockProof(const CBlockIndex& block)
arith_uint256 uint256_nthRoot(const int root, const arith_uint256 bn)
{
assert(root > 1);
if (bn==0)
return 0;
assert(bn > 0);

// starting approximation
int nRootBits = (bn.bits() + root - 1) / root;
int nStartingBits = std::min(8, nRootBits);
arith_uint256 bnUpper = bn;
bnUpper >>= (nRootBits - nStartingBits)*root;
arith_uint256 bnCur = 0;
for (int i = nStartingBits - 1; i >= 0; i--) {
arith_uint256 bnNext = bnCur;
bnNext += 1 << i;
arith_uint256 bnPower = 1;
for (int j = 0; j < root; j++)
bnPower *= bnNext;
if (bnPower <= bnUpper)
bnCur = bnNext;
}
if (nRootBits == nStartingBits)
return bnCur;
bnCur <<= nRootBits - nStartingBits;

// iterate: cur = cur + (bn / cur^^(root-1) - cur)/root
arith_uint256 bnDelta;
const arith_uint256 bnRoot = root;
int nTerminate = 0;
bool fNegativeDelta = false;
// this should always converge in fewer steps, but limit just in case
for (int it = 0; it < 20; it++)
{
arith_uint256 bnDenominator = 1;
for (int i = 0; i < root - 1; i++)
bnDenominator *= bnCur;
if (bnCur > bn/bnDenominator)
fNegativeDelta = true;
if (bnCur == bn/bnDenominator) // bnDelta=0
return bnCur;
if (fNegativeDelta) {
bnDelta = bnCur - bn/bnDenominator;
if (nTerminate == 1)
return bnCur - 1;
fNegativeDelta = false;
if (bnDelta <= bnRoot) {
bnCur -= 1;
nTerminate = -1;
continue;
}
fNegativeDelta = true;
} else {
bnDelta = bn/bnDenominator - bnCur;
if (nTerminate == -1)
return bnCur;
if (bnDelta <= bnRoot) {
bnCur += 1;
nTerminate = 1;
continue;
}
}
if (fNegativeDelta) {
bnCur -= bnDelta / bnRoot;
} else {
bnCur += bnDelta / bnRoot;
}
nTerminate = 0;
}
return bnCur;
}

arith_uint256 GetBlockProofBase(const CBlockIndex& block)
{
arith_uint256 bnTarget;
bool fNegative;
Expand All @@ -133,6 +206,77 @@ arith_uint256 GetBlockProof(const CBlockIndex& block)
return (~bnTarget / (bnTarget + 1)) + 1;
}

arith_uint256 GetPrevWorkForAlgoWithDecay(const CBlockIndex& block, int algo)
{
int nDistance = 0;
arith_uint256 nWork;
const CBlockIndex* pindex = &block;
while (pindex != NULL)
{
if (nDistance > 100)
{
return arith_uint256(0);
}
if (pindex->GetAlgo() == algo)
{
arith_uint256 nWork = GetBlockProofBase(*pindex);
nWork *= (100 - nDistance);
nWork /= 100;
return nWork;
}
pindex = pindex->pprev;
nDistance++;
}
return arith_uint256(0);
}

arith_uint256 GetGeometricMeanPrevWork(const CBlockIndex& block)
{
arith_uint256 bnRes;
arith_uint256 nBlockWork = GetBlockProofBase(block);
int nAlgo = block.GetAlgo();

// Compute the geometric mean
// We use the nthRoot product rule here:
// nthRoot(a*b*...) = nthRoot(a)*nthRoot(b)*...
// This is to ensure we never overflow a uint256.
nBlockWork = uint256_nthRoot(NUM_ALGOS, nBlockWork);

for (int algo = 0; algo < NUM_ALGOS_IMPL; algo++)
{
if (algo != nAlgo)
{
arith_uint256 nBlockWorkAlt = GetPrevWorkForAlgoWithDecay(block, algo);
if (nBlockWorkAlt != 0)
nBlockWork *= uint256_nthRoot(NUM_ALGOS,nBlockWorkAlt); // Again, the nthRoot product rule.
}
}
// In the past we have computed the geometric mean here,
// but do not need to from the nthRoot product rule above.
bnRes = nBlockWork;

// Scale to roughly match the old work calculation
bnRes <<= 8;

return bnRes;

}

arith_uint256 GetBlockProof(const CBlockIndex& block)
{
Consensus::Params params = Params().GetConsensus();
int nHeight = block.nHeight;

if(nHeight > params.nStartMultiAlgoHash)
{
return GetGeometricMeanPrevWork(block);
}
else
{
return GetBlockProofBase(block);
}
}

int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
{
arith_uint256 r;
Expand Down Expand Up @@ -168,3 +312,15 @@ const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex*
assert(pa == pb);
return pa;
}

const CBlockIndex* GetLastBlockIndexForAlgo(const CBlockIndex* pindex, int algo)
{
for (;;)
{
if (!pindex)
return NULL;
if (pindex->GetAlgo() == algo)
return pindex;
pindex = pindex->pprev;
}
}
12 changes: 9 additions & 3 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,14 @@ class CBlockIndex
return *phashBlock;
}

uint256 GetBlockPoWHash() const
uint256 GetBlockPoWHash(const Consensus::Params& params) const
{
return GetBlockHeader().GetPoWHash(nHeight);
return GetBlockHeader().GetPoWHash(nHeight, params);
}

int GetAlgo() const
{
return ::GetAlgo(nVersion);
}

int64_t GetBlockTime() const
Expand Down Expand Up @@ -369,7 +374,8 @@ arith_uint256 GetBlockProof(const CBlockIndex& block);
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&);
/** Find the forking point between two chain tips. */
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb);

/** Return the index to the last block of algo */
const CBlockIndex* GetLastBlockIndexForAlgo(const CBlockIndex* pindex, int algo);

/** Used to marshal pointers into hashes for db storage. */
class CDiskBlockIndex : public CBlockIndex
Expand Down
35 changes: 30 additions & 5 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ class CMainParams : public CChainParams {
// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x4b151d928c0aae106c9d69347df59e0088cbd33dd659deab126506865a8b0060"); //898726

consensus.nStartLyra2reHash = 208301; // height where lyra2re replaced scrypt-n
consensus.nStartLyra2re2Hash = 347000; // height where lyra2re2 replaced lyra2re
consensus.nStartLyra2re3Hash = 1080000; // height where lyra2re3 replaced lyra2re2
consensus.nStartMultiAlgoHash = 10000000; // height where multi-algorithm is active - UPDATE

consensus.nStartKGWWorkCalc = 26754; // height where KimotoGravityWell replaces bitcoin's difficulty algorithm

// multishield parameters
consensus.nAveragingInterval = 10; // 10 blocks
consensus.nMaxAdjustDown = 16; // 16% adjustment down
consensus.nMaxAdjustUp = 8; // 8% adjustment up

/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
Expand Down Expand Up @@ -181,7 +193,7 @@ class CTestNetParams : public CChainParams {
strNetworkID = "test";
consensus.testnet = true;
consensus.nSubsidyHalvingInterval = 840000;
consensus.BIP16Height = 0;
consensus.BIP16Height = 0;
consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 3.5 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 2.5 * 60;
Expand All @@ -193,24 +205,37 @@ class CTestNetParams : public CChainParams {
// Deployment of BIP65, BIP66, and BIP34.
consensus.vDeployments[Consensus::DEPLOYMENT_NVERSIONBIPS].bit = 2;
consensus.vDeployments[Consensus::DEPLOYMENT_NVERSIONBIPS].nStartTime = 1486865123;
consensus.vDeployments[Consensus::DEPLOYMENT_NVERSIONBIPS].nTimeout = 1517356801;
consensus.vDeployments[Consensus::DEPLOYMENT_NVERSIONBIPS].nTimeout = 1517356801;

// Deployment of BIP68, BIP112, and BIP113.
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1486865123;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1517356801;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1486865123;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1517356801;

// Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1486865123;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1517356801;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1517356801;

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000000000100010");

// By default assume that the signatures in ancestors of this block are valid.
consensus.defaultAssumeValid = uint256S("0x69ab56f74d75afa90b65b1fe10df8adaf2769e2ba64df1e1dc99c4d6717e1a2a"); //9000

consensus.nStartLyra2reHash = 0; // height where lyra2re replaced scrypt-n
consensus.nStartLyra2re2Hash = 0; // height where lyra2re2 replaced lyra2re
consensus.nStartLyra2re3Hash = 158220; // height where lyra2re3 replaced lyra2re2
consensus.nStartMultiAlgoHash = 210000; // height where multi-algorithm is active - UPDATE

consensus.nStartKGWWorkCalc = 2116; // height where KimotoGravityWell replaces bitcoin's difficulty algorithm

// multishield parameters
consensus.nAveragingInterval = 10; // 10 blocks
consensus.nMaxAdjustDown = 16; // 16% adjustment down
consensus.nMaxAdjustUp = 8; // 8% adjustment up
consensus.nLocalTargetAdjustment = 4; //target adjustment per algo

pchMessageStart[0] = 'v';
pchMessageStart[1] = 'e';
pchMessageStart[2] = 'r';
Expand Down
10 changes: 10 additions & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ struct Params {
uint256 nMinimumChainWork;
uint256 defaultAssumeValid;
bool testnet;

int nStartLyra2reHash;
int nStartLyra2re2Hash;
int nStartLyra2re3Hash;
int nStartMultiAlgoHash;
int nStartKGWWorkCalc;
int nAveragingInterval;
int nMaxAdjustDown;
int nMaxAdjustUp;
int nLocalTargetAdjustment;
};
} // namespace Consensus

Expand Down
15 changes: 14 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ std::string LicenseInfo()
const std::string URL_SOURCE_CODE = "<https://github.com/vertcoin-project/vertcoin-core>";
const std::string URL_WEBSITE = "<https://vertcoin.org>";

return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2014, COPYRIGHT_YEAR) + " ",
return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2014, COPYRIGHT_YEAR) + " ",
strprintf(_("Copyright (C) %i-%i"), 2009, COPYRIGHT_YEAR) + " ") + "\n" +
"\n" +
strprintf(_("Please contribute if you find %s useful. "
Expand Down Expand Up @@ -1156,6 +1156,19 @@ bool AppInitParameterInteraction()
}
}
}

// Set Mining Algorithm
std::string strAlgo = gArgs.GetArg("-algo", "lyra2rev3");
transform(strAlgo.begin(),strAlgo.end(),strAlgo.begin(),::tolower);
if (strAlgo == "lyra2rev3" || strAlgo == "lyra2re3" || strAlgo == "lyra2re")
miningAlgo = ALGO_LYRA2REV3;
else if (strAlgo == "newalgo1")
miningAlgo = ALGO_NEWALGO1;
else if (strAlgo == "newalgo2")
miningAlgo = ALGO_NEWALGO2;
else
miningAlgo = ALGO_LYRA2REV3;

return true;
}

Expand Down
9 changes: 6 additions & 3 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam

// Updating time can change work required on testnet:
if (consensusParams.fPowAllowMinDifficultyBlocks)
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams, pblock->GetAlgo());

return nNewTime - nOldTime;
}
Expand Down Expand Up @@ -105,7 +105,7 @@ void BlockAssembler::resetBlock()
nFees = 0;
}

std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, int algo, bool fMineWitnessTx)
{
int64_t nTimeStart = GetTimeMicros();

Expand Down Expand Up @@ -133,6 +133,9 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
if (chainparams.MineBlocksOnDemand())
pblock->nVersion = gArgs.GetArg("-blockversion", pblock->nVersion);

// multi-algo: encode algo into nVersion
pblock->SetAlgo(algo);

pblock->nTime = GetAdjustedTime();
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();

Expand Down Expand Up @@ -174,7 +177,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus(), algo);
pblock->nNonce = 0;
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);

Expand Down
2 changes: 1 addition & 1 deletion src/miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ class BlockAssembler
BlockAssembler(const CChainParams& params, const Options& options);

/** Construct a new block template with coinbase to scriptPubKeyIn */
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx=true);
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn, int algo, bool fMineWitnessTx=true);

private:
// utility functions
Expand Down
Loading