Anoncoin  0.9.4
P2P Digital Currency
main2.cpp
Go to the documentation of this file.
1 // Protocol 1 & 2
2 
3 static const int64_t nTargetTimespan = 86184; //420 * 205.2; = 86184 // Anoncoin: 420 blocks
4 static const int64_t nTargetSpacing = 205; //3.42 * 60; // Anoncoin: 3.42 minutes
5 static const int64_t nInterval = nTargetTimespan / nTargetSpacing;
6 
7 static const int nDifficultySwitchHeight = 15420;
8 static const int nDifficultySwitchHeight2 = 77777;
9 
10 // Protocol 3
11 static const int nDifficultyProtocol3 = 87777;
12 
13 
14 int64_t GetBlockValue(int nHeight, int64_t nFees)
15 {
16  int64_t nSubsidy = 5 * COIN;
17  // Some adjustments to the start of the lifetime to Anoncoin
18  if (nHeight < 42000) {
19  nSubsidy = 4.2 * COIN;
20  } else if (nHeight < 77777) { // All luck is seven ;)
21  nSubsidy = 7 * COIN;
22  } else if (nHeight == 77778) {
23  nSubsidy = 10 * COIN;
24  } else {
25  nSubsidy >>= (nHeight / 306600); // Anoncoin: 306600 blocks in ~2 years
26  }
27  return nSubsidy + nFees;
28 }
29 
30 
31 //
32 // minimum amount of work that could possibly be required nTime after
33 // minimum work required was nBase
34 //
35 unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
36 {
37  // ToDo: Which Algo?
39 
40  // Testnet has min-difficulty blocks
41  // after nTargetSpacing*2 time between blocks:
42  if (TestNet() && nTime > nTargetSpacing*2)
43  return bnLimit.GetCompact();
44 
45  CBigNum bnResult;
46  bnResult.SetCompact(nBase);
47  while (nTime > 0 && bnResult < bnLimit)
48  {
49  // Maximum 141% adjustment...
50  bnResult = (bnResult * 99) / 70;
51  // ... in best-case exactly 4-times-normal target time
52  nTime -= nTargetTimespan*4;
53  }
54  if (bnResult > bnLimit)
55  bnResult = bnLimit;
56  return bnResult.GetCompact();
57 }
58 
59 
60 /*
61  * Current difficulty formula, Anoncoin - kimoto gravity well
62  */
63 unsigned int static KimotoGravityWell(const CBlockIndex* pindexLast,
64  const CBlockHeader *pblock,
65  uint64_t TargetBlocksSpacingSeconds,
66  uint64_t PastBlocksMin,
67  uint64_t PastBlocksMax) {
68 
69  const CBlockIndex *BlockLastSolved = pindexLast;
70  const CBlockIndex *BlockReading = pindexLast;
71  const CBlockHeader *BlockCreating = pblock;
72 
73  uint64_t PastBlocksMass = 0;
74  int64_t PastRateActualSeconds = 0;
75  int64_t PastRateTargetSeconds = 0;
76  double PastRateAdjustmentRatio = double(1);
77  CBigNum PastDifficultyAverage;
78  CBigNum PastDifficultyAveragePrev;
79  double EventHorizonDeviation;
80  double EventHorizonDeviationFast;
81  double EventHorizonDeviationSlow;
82  CBigNum bnProofOfWorkLimit = Params().ProofOfWorkLimit( CChainParams::SCRYPT_ANC );
83 
84  if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) { return bnProofOfWorkLimit.GetCompact(); }
85 
86  for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
87  if (PastBlocksMax > 0 && i > PastBlocksMax) { break; }
88  PastBlocksMass++;
89 
90  if (i == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); }
91  else { PastDifficultyAverage = ((CBigNum().SetCompact(BlockReading->nBits) - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev; }
92  PastDifficultyAveragePrev = PastDifficultyAverage;
93 
94  PastRateActualSeconds = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime();
95  PastRateTargetSeconds = TargetBlocksSpacingSeconds * PastBlocksMass;
96  PastRateAdjustmentRatio = double(1);
97  if (PastRateActualSeconds < 0) { PastRateActualSeconds = 0; }
98  if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
99  PastRateAdjustmentRatio = double(PastRateTargetSeconds) / double(PastRateActualSeconds);
100  }
101  EventHorizonDeviation = 1 + (0.7084 * pow((double(PastBlocksMass)/double(144)), -1.228));
102  EventHorizonDeviationFast = EventHorizonDeviation;
103  EventHorizonDeviationSlow = 1 / EventHorizonDeviation;
104 
105  if (PastBlocksMass >= PastBlocksMin) {
106  if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast)) { assert(BlockReading); break; }
107  }
108  if (BlockReading->pprev == NULL) { assert(BlockReading); break; }
109  BlockReading = BlockReading->pprev;
110  }
111 
112  CBigNum bnNew(PastDifficultyAverage);
113  if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) {
114  bnNew *= PastRateActualSeconds;
115  bnNew /= PastRateTargetSeconds;
116  }
117  if (bnNew > bnProofOfWorkLimit) { bnNew = bnProofOfWorkLimit; }
118 
120  // LogPrintf("Difficulty Retarget - Kimoto Gravity Well\n");
121  // LogPrintf("PastRateAdjustmentRatio = %g\n", PastRateAdjustmentRatio);
122  // LogPrintf("Before: %08x %s\n", BlockLastSolved->nBits, CBigNum().SetCompact(BlockLastSolved->nBits).getuint256().ToString().c_str());
123  // LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString().c_str());
124 
125  return bnNew.GetCompact();
126 }
127 
128 
129 unsigned int static NeoGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
130 {
131  static const int64_t BlocksTargetSpacing = 3 * 60; // 3 minutes
132  unsigned int TimeDaySeconds = 60 * 60 * 24;
133  int64_t PastSecondsMin = TimeDaySeconds * 0.25;
134  int64_t PastSecondsMax = TimeDaySeconds * 7;
135  uint64_t PastBlocksMin = PastSecondsMin / BlocksTargetSpacing;
136  uint64_t PastBlocksMax = PastSecondsMax / BlocksTargetSpacing;
137 
138  return KimotoGravityWell(pindexLast, pblock, BlocksTargetSpacing, PastBlocksMin, PastBlocksMax);
139 }
140 
141 
142 unsigned int static OldGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
143 {
144  // ToDo: Which Algo?
145  CBigNum bnProofOfWorkLimit = Params().ProofOfWorkLimit( CChainParams::SCRYPT_ANC );
146  unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact();
147 
148  // Genesis block
149  if (pindexLast == NULL)
150  return nProofOfWorkLimit;
151 
152  // Anoncoin difficulty adjustment protocol switch (Thanks to FeatherCoin for this idea)
153 
154  static const int newTargetTimespan = 2050;
155  int nHeight = pindexLast->nHeight + 1;
156  bool fNewDifficultyProtocol = (nHeight >= nDifficultySwitchHeight || TestNet());
157  bool fNewDifficultyProtocol2 = (nHeight >= nDifficultySwitchHeight2 || TestNet());
158  if (fNewDifficultyProtocol2) {
159  // Jumping back to sqrt(2) as the factor of adjustment.
160  fNewDifficultyProtocol = false;
161  }
162 
163  int64_t nTargetTimespanCurrent = fNewDifficultyProtocol ? (nTargetTimespan*4) : nTargetTimespan;
164  int64_t nInterval = nTargetTimespanCurrent / nTargetSpacing;
165 
166  if (fNewDifficultyProtocol2) nTargetTimespanCurrent = newTargetTimespan;
167  if (TestNet() && nHeight < (newTargetTimespan/205)+1) return pindexLast->nBits;
168 
169  // Only change once per interval, or at protocol switch height
170  if ((nHeight % nInterval != 0 && !fNewDifficultyProtocol2) &&
171  (nHeight != nDifficultySwitchHeight) && !TestNet())
172  {
173  return pindexLast->nBits;
174  }
175 
176  // Anoncoin: This fixes an issue where a 51% attack can change difficulty at will.
177  // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz
178  int blockstogoback = nInterval-1;
179  if ((pindexLast->nHeight+1) != nInterval)
180  blockstogoback = nInterval;
181 
182  // Go back by what we want to be 14 days worth of blocks
183  const CBlockIndex* pindexFirst = pindexLast;
184  blockstogoback = fNewDifficultyProtocol2 ? (newTargetTimespan/205) : blockstogoback;
185  for (int i = 0; pindexFirst && i < blockstogoback; i++)
186  pindexFirst = pindexFirst->pprev;
187  assert(pindexFirst);
188 
189  // Limit adjustment step
190  int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
191  int64_t nActualTimespanMax = fNewDifficultyProtocol ? (nTargetTimespanCurrent*4) : ((nTargetTimespanCurrent*99)/70);
192  int64_t nActualTimespanMin = fNewDifficultyProtocol ? (nTargetTimespanCurrent/4) : ((nTargetTimespanCurrent*70)/99);
193  LogPrintf(" nActualTimespan = %lld before bounds\n", nActualTimespan);
194  if (pindexLast->nHeight+1 >= nDifficultySwitchHeight2) {
195  if (nActualTimespan < nActualTimespanMin)
196  nActualTimespan = nActualTimespanMin;
197  if (nActualTimespan > nActualTimespanMax)
198  nActualTimespan = nActualTimespanMax;
199  } else if (pindexLast->nHeight+1 > nDifficultySwitchHeight) {
200  if (nActualTimespan < nActualTimespanMin/4)
201  nActualTimespan = nActualTimespanMin/4;
202  if (nActualTimespan > nActualTimespanMax)
203  nActualTimespan = nActualTimespanMax;
204  } else {
205  if (nActualTimespan < nActualTimespanMin)
206  nActualTimespan = nActualTimespanMin;
207  if (nActualTimespan > nActualTimespanMax)
208  nActualTimespan = nActualTimespanMax;
209  }
210 
211  // Retarget
212  CBigNum bnNew;
213  bnNew.SetCompact(pindexLast->nBits);
214  bnNew *= nActualTimespan;
215  if (fNewDifficultyProtocol2) {
216  bnNew /= nTargetTimespanCurrent;
217  } else {
218  bnNew /= nTargetTimespan;
219  }
220 
221  if (bnNew > bnProofOfWorkLimit) bnNew = bnProofOfWorkLimit;
222 
224  LogPrintf("GetNextWorkRequired RETARGET\n");
225  LogPrintf("nTargetTimespan = %lld nActualTimespan = %lld\n", nTargetTimespan, nActualTimespan);
226  LogPrintf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString());
227  LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString());
228 
229  return bnNew.GetCompact();
230 }
231 
232 unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
233 {
234  assert(pindexLast);
235  if (pindexLast->nHeight > nDifficultyProtocol3 || TestNet()) {
236  return NeoGetNextWorkRequired(pindexLast, pblock);
237  } else {
238  return OldGetNextWorkRequired(pindexLast, pblock);
239  }
240 }
241 
242 
243 bool CheckProofOfWork(uint256 hash, unsigned int nBits)
244 {
245  CBigNum bnTarget;
246  bnTarget.SetCompact(nBits);
247 
248  // Check range
249  // ToDo: Which Algo?
250  if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit( CChainParams::SCRYPT_ANC ))
251  return error("CheckProofOfWork() : nBits below minimum work");
252 
253  // Check proof of work matches claimed amount
254  if (hash > bnTarget.getuint256())
255  return error("CheckProofOfWork() : hash doesn't match nBits");
256 
257  return true;
258 }
259 
unsigned int GetNextWorkRequired(const CBlockIndex *pindexLast, const CBlockHeader *pblock)
Definition: main2.cpp:232
CBlockIndex * pprev
Definition: main.h:705
uint256 getuint256() const
Definition: bignum.h:231
bool TestNet()
Definition: chainparams.h:127
bool CheckProofOfWork(uint256 hash, unsigned int nBits)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
Definition: main2.cpp:243
unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
Calculate the minimum amount of work a received block needs, without knowing its direct parent...
Definition: main2.cpp:35
CBigNum & SetCompact(unsigned int nCompact)
Definition: bignum.h:295
int64_t GetBlockValue(int nHeight, int64_t nFees)
Definition: main2.cpp:14
#define LogPrintf(...)
Definition: util.h:118
C++ wrapper for BIGNUM (OpenSSL bignum)
Definition: bignum.h:57
unsigned int nBits
Definition: main.h:736
256-bit unsigned integer
Definition: uint256.h:532
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: main.h:698
const CChainParams & Params()
Return the currently selected parameters.
std::string ToString() const
Definition: uint256.h:341
unsigned int GetCompact() const
Definition: bignum.h:314
int nHeight
Definition: main.h:708
int64_t GetBlockTime() const
Definition: main.h:820
const CBigNum & ProofOfWorkLimit(MinedWithAlgo mwa=SCRYPT_ANC) const
Definition: chainparams.h:80
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: core.h:340