forked from Asherda/Go-VerusHash
-
Notifications
You must be signed in to change notification settings - Fork 2
/
blockhash.cpp
147 lines (131 loc) · 4.79 KB
/
blockhash.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (c) 2020 Michael Toutonghi
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "include/utilstrencodings.h"
#include "solutiondata.h"
CActivationHeight CConstVerusSolutionVector::activationHeight;
uint160 ASSETCHAINS_CHAINID = uint160(ParseHex("1af5b8015c64d39ab44c60ead8317f9f5a9b6c4c"));
[[noreturn]] void new_handler_terminate()
{
// Rather than throwing std::bad-alloc if allocation fails, terminate
// immediately to (try to) avoid chain corruption.
// Since LogPrintf may itself allocate memory, set the handler directly
// to terminate first.
std::set_new_handler(std::terminate);
fputs("Error: Out of memory. Terminating.\n", stderr);
// The log was successful, terminate now.
std::terminate();
};
// checks that the solution stored data for this header matches what is expected, ensuring that the
// values in the header match the hash of the pre-header.
bool CBlockHeader::CheckNonCanonicalData() const
{
CPBaaSPreHeader pbph(*this);
CPBaaSBlockHeader pbbh1 = CPBaaSBlockHeader(ASSETCHAINS_CHAINID, pbph);
CPBaaSBlockHeader pbbh2;
int32_t idx = GetPBaaSHeader(pbbh2, ASSETCHAINS_CHAINID);
if (idx != -1)
{
if (pbbh1.hashPreHeader == pbbh2.hashPreHeader)
{
return true;
}
}
return false;
}
// checks that the solution stored data for this header matches what is expected, ensuring that the
// values in the header match the hash of the pre-header.
bool CBlockHeader::CheckNonCanonicalData(uint160 &cID) const
{
CPBaaSPreHeader pbph(*this);
CPBaaSBlockHeader pbbh1 = CPBaaSBlockHeader(cID, pbph);
CPBaaSBlockHeader pbbh2;
int32_t idx = GetPBaaSHeader(pbbh2, cID);
if (idx != -1)
{
if (pbbh1.hashPreHeader == pbbh2.hashPreHeader)
{
return true;
}
}
return false;
}
uint256 CBlockHeader::GetVerusV2Hash() const
{
if (hashPrevBlock.IsNull())
{
// always use SHA256D for genesis block
return SerializeHash(*this);
}
else
{
if (nVersion == VERUS_V2)
{
int solutionVersion = CConstVerusSolutionVector::Version(nSolution);
// in order for this to work, the PBaaS hash of the pre-header must match the header data
// otherwise, it cannot clear the canonical data and hash in a chain-independent manner
int pbaasType = CConstVerusSolutionVector::HasPBaaSHeader(nSolution);
bool debugPrint = false;
if (pbaasType != 0 && CheckNonCanonicalData())
{
CBlockHeader bh = CBlockHeader(*this);
bh.ClearNonCanonicalData();
return SerializeVerusHashV2b(bh, solutionVersion);
}
else
{
return SerializeVerusHashV2b(*this, solutionVersion);
}
}
else
{
return SerializeVerusHash(*this);
}
}
}
// returns -1 on failure, upon failure, pbbh is undefined and likely corrupted
int32_t CBlockHeader::GetPBaaSHeader(CPBaaSBlockHeader &pbh, const uint160 &cID) const
{
// find the specified PBaaS header in the solution and return its index if present
// if not present, return -1
if (nVersion == VERUS_V2)
{
// search in the solution for this header index and return it if found
CPBaaSSolutionDescriptor d = CVerusSolutionVector::solutionTools.GetDescriptor(nSolution);
if (CVerusSolutionVector::solutionTools.HasPBaaSHeader(nSolution) != 0)
{
int32_t numHeaders = d.numPBaaSHeaders;
const CPBaaSBlockHeader *ppbbh = CVerusSolutionVector::solutionTools.GetFirstPBaaSHeader(nSolution);
for (int32_t i = 0; i < numHeaders; i++)
{
if ((ppbbh + i)->chainID == cID)
{
pbh = *(ppbbh + i);
return i;
}
}
}
}
return -1;
}
CPBaaSPreHeader::CPBaaSPreHeader(const CBlockHeader &bh)
{
hashPrevBlock = bh.hashPrevBlock;
hashMerkleRoot = bh.hashMerkleRoot;
hashFinalSaplingRoot = bh.hashFinalSaplingRoot;
nNonce = bh.nNonce;
nBits = bh.nBits;
CPBaaSSolutionDescriptor descr = CConstVerusSolutionVector::GetDescriptor(bh.nSolution);
if (descr.version >= CConstVerusSolutionVector::activationHeight.ACTIVATE_PBAAS_HEADER)
{
hashPrevMMRRoot = descr.hashPrevMMRRoot;
hashBlockMMRRoot = descr.hashBlockMMRRoot;
}
}
CPBaaSBlockHeader::CPBaaSBlockHeader(const uint160 &cID, const CPBaaSPreHeader &pbph) : chainID(cID)
{
CBLAKE2bWriter hw(SER_GETHASH, 0);
// all core data besides version, and solution, which are shared across all headers
hw << pbph;
hashPreHeader = hw.GetHash();
}