]> Git Repo - VerusCoin.git/blame - src/pow.cpp
Introduce librustzcash and Rust to depends system.
[VerusCoin.git] / src / pow.cpp
CommitLineData
df852d2b 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
78253fcb 3// Distributed under the MIT software license, see the accompanying
df852d2b 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include "pow.h"
7
6a0c7cea
SB
8#include "librustzcash.h"
9
734f85c4 10#include "arith_uint256.h"
22c4272b 11#include "chain.h"
fdda3c50
JG
12#include "chainparams.h"
13#include "crypto/equihash.h"
d2270111 14#include "primitives/block.h"
fdda3c50 15#include "streams.h"
df852d2b 16#include "uint256.h"
ad49c256 17#include "util.h"
df852d2b 18
fdda3c50
JG
19#include "sodium.h"
20
d698ef69 21unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
df852d2b 22{
fd311996 23 unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
df852d2b 24
25 // Genesis block
26 if (pindexLast == NULL)
27 return nProofOfWorkLimit;
28
f2c48e15
JG
29 // Find the first block in the averaging interval
30 const CBlockIndex* pindexFirst = pindexLast;
7b173bd8 31 arith_uint256 bnTot {0};
f2c48e15 32 for (int i = 0; pindexFirst && i < params.nPowAveragingWindow; i++) {
7b173bd8
JG
33 arith_uint256 bnTmp;
34 bnTmp.SetCompact(pindexFirst->nBits);
35 bnTot += bnTmp;
f2c48e15
JG
36 pindexFirst = pindexFirst->pprev;
37 }
38
39 // Check we have enough blocks
40 if (pindexFirst == NULL)
41 return nProofOfWorkLimit;
df852d2b 42
7b173bd8
JG
43 arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow};
44
29842505 45 return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params);
34e5015c
RN
46}
47
29842505
JG
48unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
49 int64_t nLastBlockTime, int64_t nFirstBlockTime,
50 const Consensus::Params& params)
34e5015c 51{
df852d2b 52 // Limit adjustment step
f2c48e15 53 // Use medians to prevent time-warp attacks
e99731b4 54 int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
f2c48e15
JG
55 LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan);
56 nActualTimespan = params.AveragingWindowTimespan() + (nActualTimespan - params.AveragingWindowTimespan())/4;
57 LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan);
58
59 if (nActualTimespan < params.MinActualTimespan())
60 nActualTimespan = params.MinActualTimespan();
61 if (nActualTimespan > params.MaxActualTimespan())
62 nActualTimespan = params.MaxActualTimespan();
df852d2b 63
64 // Retarget
fd311996 65 const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
29842505 66 arith_uint256 bnNew {bnAvg};
f2c48e15 67 bnNew /= params.AveragingWindowTimespan();
aa86873a 68 bnNew *= nActualTimespan;
df852d2b 69
fd311996
CF
70 if (bnNew > bnPowLimit)
71 bnNew = bnPowLimit;
df852d2b 72
73 /// debug print
f2c48e15
JG
74 LogPrint("pow", "GetNextWorkRequired RETARGET\n");
75 LogPrint("pow", "params.AveragingWindowTimespan() = %d nActualTimespan = %d\n", params.AveragingWindowTimespan(), nActualTimespan);
29842505 76 LogPrint("pow", "Current average: %08x %s\n", bnAvg.GetCompact(), bnAvg.ToString());
f2c48e15 77 LogPrint("pow", "After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString());
df852d2b 78
79 return bnNew.GetCompact();
80}
81
fdda3c50
JG
82bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params)
83{
e9574728
JG
84 unsigned int n = params.EquihashN();
85 unsigned int k = params.EquihashK();
fdda3c50
JG
86
87 // Hash state
88 crypto_generichash_blake2b_state state;
e9574728 89 EhInitialiseState(n, k, state);
fdda3c50
JG
90
91 // I = the block header minus nonce and solution.
92 CEquihashInput I{*pblock};
93 // I||V
94 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
95 ss << I;
96 ss << pblock->nNonce;
97
98 // H(I||V||...
99 crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
100
6a0c7cea
SB
101 // Ensure that our Rust interactions are working in production builds. This is
102 // temporary and should be removed.
103 {
104 assert(librustzcash_xor(0x0f0f0f0f0f0f0f0f, 0x1111111111111111) == 0x1e1e1e1e1e1e1e1e);
105 }
106
e9574728
JG
107 bool isValid;
108 EhIsValidSolution(n, k, state, pblock->nSolution, isValid);
109 if (!isValid)
fdda3c50
JG
110 return error("CheckEquihashSolution(): invalid solution");
111
112 return true;
113}
114
d698ef69 115bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
df852d2b 116{
117 bool fNegative;
118 bool fOverflow;
734f85c4 119 arith_uint256 bnTarget;
f0fd00cb 120
df852d2b 121 bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
122
123 // Check range
fd311996 124 if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
5262fde0 125 return error("CheckProofOfWork(): nBits below minimum work");
df852d2b 126
127 // Check proof of work matches claimed amount
734f85c4 128 if (UintToArith256(hash) > bnTarget)
5262fde0 129 return error("CheckProofOfWork(): hash doesn't match nBits");
df852d2b 130
131 return true;
132}
133
734f85c4 134arith_uint256 GetBlockProof(const CBlockIndex& block)
b343c1a1 135{
734f85c4 136 arith_uint256 bnTarget;
b343c1a1 137 bool fNegative;
138 bool fOverflow;
092b58d1 139 bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
b343c1a1 140 if (fNegative || fOverflow || bnTarget == 0)
141 return 0;
142 // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
734f85c4 143 // as it's too large for a arith_uint256. However, as 2**256 is at least as large
b343c1a1 144 // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
145 // or ~bnTarget / (nTarget+1) + 1.
146 return (~bnTarget / (bnTarget + 1)) + 1;
df852d2b 147}
f7303f97
PW
148
149int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params)
150{
151 arith_uint256 r;
152 int sign = 1;
153 if (to.nChainWork > from.nChainWork) {
154 r = to.nChainWork - from.nChainWork;
155 } else {
156 r = from.nChainWork - to.nChainWork;
157 sign = -1;
158 }
159 r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip);
160 if (r.bits() > 63) {
161 return sign * std::numeric_limits<int64_t>::max();
162 }
163 return sign * r.GetLow64();
164}
This page took 0.154396 seconds and 4 git commands to generate.