]>
Commit | Line | Data |
---|---|---|
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 |
13 | extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH; |
14 | ||
42181656 | 15 | // default hash algorithm for block |
16 | uint256 (CBlockHeader::*CBlockHeader::hashFunction)() const = &CBlockHeader::GetSHA256DHash; | |
17 | ||
18 | uint256 CBlockHeader::GetSHA256DHash() const | |
f121db58 | 19 | { |
a0ae79d7 | 20 | return SerializeHash(*this); |
f121db58 PW |
21 | } |
22 | ||
42181656 | 23 | uint256 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 | 32 | uint256 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 | 38 | void CBlockHeader::SetSHA256DHash() |
39 | { | |
40 | CBlockHeader::hashFunction = &CBlockHeader::GetSHA256DHash; | |
41 | } | |
42 | ||
43 | void 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 | |
50 | bool 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 | |
77 | uint256 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 | 89 | uint256 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 | ||
152 | std::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 | ||
168 | uint256 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 | 183 | std::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 | } |