]> Git Repo - VerusCoin.git/blame - src/primitives/block.cpp
PoS improvements
[VerusCoin.git] / src / primitives / block.cpp
CommitLineData
effc2770 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
effc2770
EL
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
d2270111 6#include "primitives/block.h"
51ed9ec9 7
85c579e3 8#include "hash.h"
9b6d4c5c 9#include "tinyformat.h"
85c579e3 10#include "utilstrencodings.h"
81aeb284 11#include "crypto/common.h"
05df3fc6 12
c5325a32
MT
13extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
14
42181656 15// default hash algorithm for block
16uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash;
17
18uint256 CBlockHeader::GetSHA256DHash() const
f121db58 19{
a0ae79d7 20 return SerializeHash(*this);
f121db58
PW
21}
22
42181656 23uint256 CBlockHeader::GetVerusHash() const
24{
cf1e5967 25 if (hashPrevBlock.IsNull())
42181656 26 // always use SHA256D for genesis block
27 return SerializeHash(*this);
28 else
29 return SerializeVerusHash(*this);
30}
31
4dcb64c0 32uint256 CBlockHeader::GetVerusV2Hash() const
20ab1c91
MT
33{
34 // no check for genesis block and use the optimized hash
4dcb64c0 35 return SerializeVerusHashV2(*this);
20ab1c91
MT
36}
37
42181656 38void CBlockHeader::SetSHA256DHash()
39{
40 CBlockHeader::hashFunction = &CBlockHeader::GetSHA256DHash;
41}
42
43void CBlockHeader::SetVerusHash()
44{
45 CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash;
46}
47
c5325a32
MT
48// returns false if unable to fast calculate the VerusPOSHash from the header. it can still be calculated from the block
49// in that case
50bool CBlockHeader::GetVerusPOSHash(uint256 &value, int32_t nHeight) const
51{
52 // if below the required height or no storage space in the solution, we can't get
53 // a cached txid value to calculate the POSHash from the header
54 if (!(CPOSNonce::NewNonceActive(nHeight) && IsVerusPOSBlock()))
55 return false;
56
57 // if we can calculate, this assumes the protocol that the POSHash calculation is:
58 // hashWriter << ASSETCHAINS_MAGIC;
59 // hashWriter << nNonce; (nNonce is:
60 // (high 128 bits == low 128 bits of verus hash of low 128 bits of nonce)
61 // (low 32 bits == compact PoS difficult)
62 // (mid 96 bits == low 96 bits of HASH(pastHash, txid, voutnum)
63 // pastHash is hash of height - 100, either PoW hash of block or PoS hash, if new PoS
64 // )
65 // hashWriter << height;
66 // return hashWriter.GetHash();
67 CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
68
69 hashWriter << ASSETCHAINS_MAGIC;
70 hashWriter << nNonce;
71 hashWriter << nHeight;
72 value = hashWriter.GetHash();
73 return true;
74}
75
76// depending on the height of the block and its type, this returns the POS hash or the POW hash
77uint256 CBlockHeader::GetVerusEntropyHash(int32_t height) const
78{
79 uint256 retVal;
80 // if we qualify as PoW, use PoW hash, regardless of PoS state
81 if (GetVerusPOSHash(retVal, height))
82 {
83 // POS hash
84 return retVal;
85 }
86 return GetHash();
87}
88
584a3589 89uint256 CBlock::BuildMerkleTree(bool* fMutated) const
f121db58 90{
584a3589
PW
91 /* WARNING! If you're reading this because you're learning about crypto
92 and/or designing a new system that will use merkle trees, keep in mind
93 that the following merkle tree algorithm has a serious flaw related to
94 duplicate txids, resulting in a vulnerability (CVE-2012-2459).
95
96 The reason is that if the number of hashes in the list at a given time
97 is odd, the last one is duplicated before computing the next level (which
98 is unusual in Merkle trees). This results in certain sequences of
99 transactions leading to the same merkle root. For example, these two
100 trees:
101
102 A A
103 / \ / \
104 B C B C
105 / \ | / \ / \
106 D E F D E F F
107 / \ / \ / \ / \ / \ / \ / \
108 1 2 3 4 5 6 1 2 3 4 5 6 5 6
109
110 for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
111 6 are repeated) result in the same root hash A (because the hash of both
112 of (F) and (F,F) is C).
113
114 The vulnerability results from being able to send a block with such a
115 transaction list, with the same merkle root, and the same block hash as
116 the original without duplication, resulting in failed validation. If the
117 receiving node proceeds to mark that block as permanently invalid
118 however, it will fail to accept further unmodified (and thus potentially
119 valid) versions of the same block. We defend against this by detecting
120 the case where we would hash two identical hashes at the end of the list
121 together, and treating that identically to the block having an invalid
122 merkle root. Assuming no double-SHA256 collisions, this will detect all
123 known ways of changing the transactions without affecting the merkle
124 root.
125 */
f121db58 126 vMerkleTree.clear();
584a3589 127 vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
e1c94677 128 for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
805344dc 129 vMerkleTree.push_back(it->GetHash());
f121db58 130 int j = 0;
584a3589 131 bool mutated = false;
f121db58
PW
132 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
133 {
134 for (int i = 0; i < nSize; i += 2)
135 {
136 int i2 = std::min(i+1, nSize-1);
584a3589
PW
137 if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
138 // Two identical hashes at the end of the list at a particular level.
139 mutated = true;
140 }
f121db58
PW
141 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
142 BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
143 }
144 j += nSize;
145 }
584a3589
PW
146 if (fMutated) {
147 *fMutated = mutated;
148 }
4f152496 149 return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
f121db58
PW
150}
151
152std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
153{
154 if (vMerkleTree.empty())
155 BuildMerkleTree();
156 std::vector<uint256> vMerkleBranch;
157 int j = 0;
158 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
159 {
160 int i = std::min(nIndex^1, nSize-1);
161 vMerkleBranch.push_back(vMerkleTree[j+i]);
162 nIndex >>= 1;
163 j += nSize;
164 }
165 return vMerkleBranch;
166}
167
168uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
169{
170 if (nIndex == -1)
4f152496 171 return uint256();
e1c94677 172 for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
f121db58
PW
173 {
174 if (nIndex & 1)
e1c94677 175 hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
f121db58 176 else
e1c94677 177 hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
f121db58
PW
178 nIndex >>= 1;
179 }
180 return hash;
181}
182
81212588 183std::string CBlock::ToString() const
f121db58 184{
81212588 185 std::stringstream s;
a8d384ae 186 s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, hashReserved=%s, nTime=%u, nBits=%08x, nNonce=%s, vtx=%u)\n",
7d9d134b 187 GetHash().ToString(),
f121db58 188 nVersion,
7d9d134b
WL
189 hashPrevBlock.ToString(),
190 hashMerkleRoot.ToString(),
a8d384ae 191 hashReserved.ToString(),
fdda3c50 192 nTime, nBits, nNonce.ToString(),
f121db58
PW
193 vtx.size());
194 for (unsigned int i = 0; i < vtx.size(); i++)
195 {
81212588 196 s << " " << vtx[i].ToString() << "\n";
f121db58 197 }
81212588 198 s << " vMerkleTree: ";
f121db58 199 for (unsigned int i = 0; i < vMerkleTree.size(); i++)
81212588
WL
200 s << " " << vMerkleTree[i].ToString();
201 s << "\n";
202 return s.str();
f121db58 203}
This page took 0.242727 seconds and 4 git commands to generate.