]> Git Repo - VerusCoin.git/blame - src/primitives/solutiondata.h
reduce debugging output
[VerusCoin.git] / src / primitives / solutiondata.h
CommitLineData
12217420 1// Copyright (c) 2018 Michael Toutonghi
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_PRIMITIVES_SOLUTIONDATA_H
6#define BITCOIN_PRIMITIVES_SOLUTIONDATA_H
7
8#include "serialize.h"
9#include "uint256.h"
10#include "arith_uint256.h"
85c51d62 11#include "hash.h"
12#include "nonce.h"
13#include "streams.h"
12217420 14
b2a98c42 15class CPBaaSBlockHeader;
bd6639fd 16
12217420 17class CActivationHeight
18{
19 public:
20 static const int32_t MAX_HEIGHT = 0x7fffffff;
21 static const int32_t DEFAULT_UPGRADE_HEIGHT = MAX_HEIGHT;
bd6639fd 22 static const int32_t NUM_VERSIONS = 3;
90198f71 23 static const int32_t SOLUTION_VERUSV2 = 1;
bd6639fd 24 static const int32_t SOLUTION_VERUSV3 = 2;
12217420 25 bool active;
26 int32_t heights[NUM_VERSIONS];
bd6639fd 27 CActivationHeight() : heights{0, DEFAULT_UPGRADE_HEIGHT, DEFAULT_UPGRADE_HEIGHT}, active(true) {}
12217420 28
29 void SetActivationHeight(int32_t version, int32_t height)
30 {
31 assert(version < NUM_VERSIONS && version > 0);
32 if (height < MAX_HEIGHT)
33 {
34 active = true;
35 }
36 heights[version] = height;
37 }
38
90198f71 39 bool IsActivationHeight(int32_t version, int32_t height)
40 {
41 assert(version < NUM_VERSIONS && version > 0);
42 return active && heights[version] == height;
43 }
44
12217420 45 int32_t ActiveVersion(int32_t height)
46 {
47 if (!active)
48 return 0;
49
50 int32_t ver = 0;
51 for (int32_t i = 0; i < NUM_VERSIONS; i++)
52 {
53 if (heights[i] > height)
54 {
55 break;
56 }
57 ver = i;
58 }
59 return ver;
60 }
61};
62
85c51d62 63class CBlockHeader;
64
65class CPBaaSPreHeader
b2a98c42 66{
85c51d62 67public:
68 uint256 hashPrevBlock;
69 uint256 hashMerkleRoot;
70 uint256 hashFinalSaplingRoot;
71 uint256 nNonce;
72 uint32_t nBits;
73
74 CPBaaSPreHeader() : nBits(0) {}
75 CPBaaSPreHeader(const uint256 &prevBlock, const uint256 &merkleRoot, const uint256 &finalSaplingRoot,const uint256 &nonce, uint32_t compactTarget) :
76 hashPrevBlock(prevBlock), hashMerkleRoot(merkleRoot), hashFinalSaplingRoot(finalSaplingRoot), nNonce(nonce), nBits(compactTarget) {}
77
1fa4454d 78 CPBaaSPreHeader(const CBlockHeader &bh);
85c51d62 79
80 ADD_SERIALIZE_METHODS;
81
82 template <typename Stream, typename Operation>
83 inline void SerializationOp(Stream& s, Operation ser_action) {
84 READWRITE(hashPrevBlock);
85 READWRITE(hashMerkleRoot);
86 READWRITE(hashFinalSaplingRoot);
87 READWRITE(nNonce);
88 READWRITE(nBits);
89 }
f8f61a6d 90
91 void SetBlockData(CBlockHeader &bh);
85c51d62 92};
93
94// this class provides a minimal and compact hash pair and identity for a merge mined PBaaS header
95class CPBaaSBlockHeader
96{
97public:
98 uint160 chainID; // hash of unique PBaaS symbol on Verus chain
99 uint256 hashPreHeader; // hash of block before solution + chain power + block number
100 uint256 hashPrevMMRRoot; // prior block's Merkle Mountain Range
101
102 // header
103 static const size_t ID_OFFSET = 0; // offset of 32 byte ID in serialized stream
104 static const int32_t CURRENT_VERSION = CPOSNonce::VERUS_V2;
105 static const int32_t CURRENT_VERSION_MASK = 0x0000ffff; // for compatibility
106
107 CPBaaSBlockHeader()
108 {
109 SetNull();
110 }
111
112 CPBaaSBlockHeader(const uint160 &cID, const uint256 &hashPre, const uint256 &hashPrevMMR) : chainID(cID), hashPreHeader(hashPre), hashPrevMMRRoot(hashPrevMMR) { }
113
114 CPBaaSBlockHeader(const char *pbegin, const char *pend)
115 {
116 CDataStream s = CDataStream(pbegin, pend, SER_NETWORK, PROTOCOL_VERSION);
117 s >> *this;
118 }
119
f8f61a6d 120 CPBaaSBlockHeader(const uint160 &cID, const CPBaaSPreHeader &pbph, const uint256 &hashPrevMMR);
85c51d62 121
122 CPBaaSBlockHeader(const uint160 &cID,
123 const uint256 &hashPrevBlock,
124 const uint256 &hashMerkleRoot,
125 const uint256 &hashFinalSaplingRoot,
126 const uint256 &nNonce,
127 uint32_t nBits,
128 const uint256 &hashPrevMMRRoot)
129 {
130 CPBaaSPreHeader pbph(hashPrevBlock, hashMerkleRoot, hashFinalSaplingRoot, nNonce, nBits);
131
132 CHashWriter hw(SER_GETHASH, PROTOCOL_VERSION);
133 hw << pbph;
134
135 hashPreHeader = hw.GetHash();
136 }
137
138 ADD_SERIALIZE_METHODS;
139
140 template <typename Stream, typename Operation>
141 inline void SerializationOp(Stream& s, Operation ser_action) {
142 READWRITE(chainID);
143 READWRITE(hashPreHeader);
144 READWRITE(hashPrevMMRRoot);
145 }
146
147 bool operator==(const CPBaaSBlockHeader &right)
148 {
149 return (chainID == right.chainID && hashPreHeader == right.hashPreHeader && hashPrevMMRRoot == right.hashPrevMMRRoot);
150 }
151
152 bool operator!=(const CPBaaSBlockHeader &right)
153 {
154 return (chainID != right.chainID || hashPreHeader != right.hashPreHeader || hashPrevMMRRoot != right.hashPrevMMRRoot);
155 }
156
157 void SetNull()
158 {
159 chainID.SetNull();
160 hashPreHeader.SetNull();
161 hashPrevMMRRoot.SetNull();
162 }
163
164 bool IsNull() const
165 {
166 return chainID.IsNull();
167 }
b2a98c42
MT
168};
169
170enum SolutionConstants
171{
172 SOLUTION_POW = 0x1, // if set, this is a PoW solution, otherwise, not
85c51d62 173 SOLUTION_PBAAS_HEADER_SIZE = sizeof(CPBaaSBlockHeader) // size of a processed PBAAS header
b2a98c42
MT
174};
175
176class CPBaaSSolutionDescriptor
177{
178 public:
179 uint32_t version;
180 uint8_t descrBits;
181 uint8_t numPBaaSHeaders; // these come right after the base and before the stream
25eff798 182 uint16_t extraDataSize; // in PoS or possibly future blocks, this is a stream after PBaaS headers
b2a98c42 183
25eff798 184 CPBaaSSolutionDescriptor() : version(0), descrBits(0), numPBaaSHeaders(0), extraDataSize(0) {}
b2a98c42 185 CPBaaSSolutionDescriptor(uint32_t ver, uint8_t descr, uint8_t numSubHeaders, uint16_t sSize) :
25eff798 186 version(ver), descrBits(descr), numPBaaSHeaders(numSubHeaders), extraDataSize(sSize) {}
b2a98c42
MT
187 CPBaaSSolutionDescriptor(const std::vector<unsigned char> &vch)
188 {
189 version = vch[0] + (vch[1] << 8) + (vch[2] << 16) + (vch[3] << 24);
190 descrBits = vch[4];
191 numPBaaSHeaders = vch[5];
25eff798 192 extraDataSize = vch[6] | ((uint16_t)(vch[7]) << 8);
b2a98c42
MT
193 }
194 void SetVectorBase(std::vector<unsigned char> &vch)
195 {
196 if (vch.size() >= sizeof(*this))
197 {
198 vch[0] = version & 0xff;
199 vch[1] = (version >> 8) & 0xff;
200 vch[2] = (version >> 16) & 0xff;
201 vch[3] = (version >> 24) & 0xff;
202 vch[4] = descrBits;
203 vch[5] = numPBaaSHeaders;
25eff798
MT
204 vch[6] = extraDataSize & 0xff;
205 vch[7] = (extraDataSize >> 8) & 0xff;
b2a98c42
MT
206 }
207 }
208};
209
12217420 210class CConstVerusSolutionVector
211{
212 public:
12217420 213 static const bool SOLUTION_SIZE_FIXED = true;
b2a98c42
MT
214 static const uint32_t HEADER_BASESIZE = 143;
215 static const uint32_t SOLUTION_SIZE = 1344;
216 static const uint32_t OVERHEAD_SIZE = sizeof(CPBaaSSolutionDescriptor);
217
218 static CActivationHeight activationHeight;
12217420 219
220 CConstVerusSolutionVector() {}
221
222 static uint32_t GetVersionByHeight(uint32_t height)
223 {
d5040cb1 224 return activationHeight.ActiveVersion(height);
12217420 225 }
226
bd6639fd 227 static uint32_t Version(const std::vector<unsigned char> &vch)
12217420 228 {
b2a98c42 229 if (activationHeight.ActiveVersion(0x7fffffff) > 0)
12217420 230 {
b2a98c42 231 return CPBaaSSolutionDescriptor(vch).version;
12217420 232 }
233 else
234 {
235 return 0;
236 }
237 }
238
bd6639fd 239 static bool SetVersion(std::vector<unsigned char> &vch, uint32_t v)
12217420 240 {
b2a98c42
MT
241 CPBaaSSolutionDescriptor psd = CPBaaSSolutionDescriptor(vch);
242 psd.version = v;
243 if (activationHeight.active && vch.size() >= sizeof(CPBaaSSolutionDescriptor))
12217420 244 {
b2a98c42 245 psd.SetVectorBase(vch);
12217420 246 return true;
247 }
248 else
249 {
12217420 250 return false;
251 }
252 }
253
bd6639fd 254 static bool SetVersionByHeight(std::vector<unsigned char> &vch, uint32_t height)
12217420 255 {
256 return SetVersion(vch, activationHeight.ActiveVersion(height));
257 }
bd6639fd 258
b2a98c42 259 static bool SetDescriptor(std::vector<unsigned char> &vch, CPBaaSSolutionDescriptor d)
bd6639fd 260 {
b2a98c42
MT
261 d.SetVectorBase(vch);
262 }
263
264 static CPBaaSSolutionDescriptor GetDescriptor(const std::vector<unsigned char> &vch)
265 {
266 return CPBaaSSolutionDescriptor(vch);
bd6639fd
MT
267 }
268
b2a98c42 269 static uint32_t DescriptorBits(const std::vector<unsigned char> &vch)
bd6639fd 270 {
b2a98c42
MT
271 return GetDescriptor(vch).descrBits;
272 }
273
274 static uint32_t GetNumPBaaSHeaders(const std::vector<unsigned char> &vch)
275 {
276 return GetDescriptor(vch).numPBaaSHeaders;
277 }
278
25eff798
MT
279 static uint32_t MaxPBaaSHeaders(const std::vector<unsigned char> &vch)
280 {
281 auto descr = GetDescriptor(vch);
282
85c51d62 283 return descr.extraDataSize ? descr.numPBaaSHeaders : descr.numPBaaSHeaders + (uint32_t)(ExtraDataLen(vch) / sizeof(CPBaaSBlockHeader));
25eff798
MT
284 }
285
b2a98c42
MT
286 static bool SetDescriptorBits(std::vector<unsigned char> &vch, uint8_t dBits)
287 {
288 CPBaaSSolutionDescriptor psd = CPBaaSSolutionDescriptor(vch);
289 psd.descrBits = dBits;
290 if (activationHeight.active && vch.size() >= sizeof(CPBaaSSolutionDescriptor))
bd6639fd 291 {
b2a98c42 292 psd.SetVectorBase(vch);
bd6639fd
MT
293 return true;
294 }
295 else
296 {
297 return false;
298 }
299 }
300
301 // returns 0 if not PBaaS, 1 if PBaaS PoW, -1 if PBaaS PoS
302 static int32_t IsPBaaS(const std::vector<unsigned char> &vch)
303 {
304 if (Version(vch) == CActivationHeight::SOLUTION_VERUSV3)
305 {
b2a98c42 306 return (DescriptorBits(vch) & SOLUTION_POW) ? 1 : -1;
bd6639fd
MT
307 }
308 return 0;
309 }
b2a98c42
MT
310
311 static const CPBaaSBlockHeader *GetFirstPBaaSHeader(const std::vector<unsigned char> &vch)
312 {
313 return (CPBaaSBlockHeader *)(&vch[0] + sizeof(CPBaaSSolutionDescriptor)); // any headers present are right after descriptor
314 }
315
316 static void SetPBaaSHeader(std::vector<unsigned char> &vch, const CPBaaSBlockHeader &pbh, int32_t idx);
317
25eff798
MT
318 static uint32_t HeadersOverheadSize(const std::vector<unsigned char> &vch)
319 {
85c51d62 320 return GetDescriptor(vch).numPBaaSHeaders * sizeof(CPBaaSBlockHeader) + OVERHEAD_SIZE;
25eff798
MT
321 }
322
b2a98c42
MT
323 // return a vector of bytes that contains the internal data for this solution vector
324 static uint32_t ExtraDataLen(const std::vector<unsigned char> &vch)
325 {
326 int len;
327
328 if (Version(vch) < CActivationHeight::SOLUTION_VERUSV3)
329 {
330 len = 0;
331 }
332 else
333 {
334 // calculate number of bytes, minus the OVERHEAD_SIZE byte version and extra nonce at the end of the solution
25eff798 335 len = (vch.size() - ((HEADER_BASESIZE + vch.size()) % 32 + HeadersOverheadSize(vch)));
b2a98c42
MT
336 }
337
338 return len < 0 ? 0 : (uint32_t)len;
339 }
340
341 // return a vector of bytes that contains the internal data for this solution vector
342 const unsigned char *ExtraDataPtr(const std::vector<unsigned char> &vch)
343 {
344 if (ExtraDataLen(vch))
345 {
346 return &(vch.data()[OVERHEAD_SIZE]);
347 }
348 else
349 {
350 return NULL;
351 }
352 }
12217420 353};
354
355class CVerusSolutionVector
356{
357 private:
12217420 358 std::vector<unsigned char> &vch;
359
360 public:
b2a98c42 361 static CConstVerusSolutionVector solutionTools;
12217420 362
363 CVerusSolutionVector(std::vector<unsigned char> &_vch) : vch(_vch) { }
364
365 static uint32_t GetVersionByHeight(uint32_t height)
366 {
b2a98c42 367 return solutionTools.GetVersionByHeight(height);
12217420 368 }
369
370 uint32_t Version()
371 {
b2a98c42 372 return solutionTools.Version(vch);
12217420 373 }
374
375 bool SetVersion(uint32_t v)
376 {
b2a98c42 377 solutionTools.SetVersion(vch, v);
12217420 378 }
379
380 bool SetVersionByHeight(uint32_t height)
381 {
b2a98c42
MT
382 return solutionTools.SetVersionByHeight(vch, height);
383 }
384
385 CPBaaSSolutionDescriptor Descriptor()
386 {
387 return solutionTools.GetDescriptor(vch);
12217420 388 }
bd6639fd 389
b2a98c42
MT
390 void SetDescriptor(CPBaaSSolutionDescriptor d)
391 {
392 solutionTools.SetDescriptor(vch, d);
393 }
394
395 uint32_t DescriptorBits()
bd6639fd 396 {
b2a98c42 397 return solutionTools.DescriptorBits(vch);
bd6639fd
MT
398 }
399
b2a98c42 400 bool SetDescriptorBits(uint32_t d)
bd6639fd 401 {
b2a98c42 402 return solutionTools.SetDescriptorBits(vch, d);
bd6639fd
MT
403 }
404
405 // returns 0 if not PBaaS, 1 if PBaaS PoW, -1 if PBaaS PoS
406 int32_t IsPBaaS()
407 {
b2a98c42 408 return solutionTools.IsPBaaS(vch);
bd6639fd
MT
409 }
410
b2a98c42
MT
411 const CPBaaSBlockHeader *GetFirstPBaaSHeader() const
412 {
413 return solutionTools.GetFirstPBaaSHeader(vch);
414 }
415
416 uint32_t GetNumPBaaSHeaders() const
417 {
418 return solutionTools.GetNumPBaaSHeaders(vch);
419 }
420
421 bool GetPBaaSHeader(CPBaaSBlockHeader &pbh, uint32_t idx) const;
422
423 void SetPBaaSHeader(const CPBaaSBlockHeader &pbh, uint32_t idx)
424 {
425 solutionTools.SetPBaaSHeader(vch, pbh, idx);
426 }
427
25eff798
MT
428 uint32_t HeadersOverheadSize()
429 {
85c51d62 430 return Descriptor().numPBaaSHeaders * sizeof(CPBaaSBlockHeader) + solutionTools.OVERHEAD_SIZE;
25eff798
MT
431 }
432
b2a98c42 433 // return length of the internal data for this solution vector
bd6639fd
MT
434 uint32_t ExtraDataLen()
435 {
436 int len;
437
438 if (Version() < CActivationHeight::SOLUTION_VERUSV3)
439 {
440 len = 0;
441 }
442 else
443 {
444 // calculate number of bytes, minus the OVERHEAD_SIZE byte version and extra nonce at the end of the solution
25eff798 445 len = (vch.size() - ((solutionTools.HEADER_BASESIZE + vch.size()) % 32 + HeadersOverheadSize()));
bd6639fd
MT
446 }
447
448 return len < 0 ? 0 : (uint32_t)len;
449 }
450
ec1c84a0
MT
451 uint32_t GetRequiredSolutionSize(uint32_t extraDataLen)
452 {
453 // round up to nearest 32 bytes
25eff798
MT
454 uint32_t overhead = HeadersOverheadSize();
455
456 // make sure we have 15 bytes extra for hashing properly
457 return extraDataLen + overhead + (47 - ((extraDataLen + overhead + solutionTools.HEADER_BASESIZE) % 32));
ec1c84a0
MT
458 }
459
460 void ResizeExtraData(uint32_t newSize)
461 {
462 vch.resize(GetRequiredSolutionSize(newSize));
463 }
464
b2a98c42 465 // return a pointer to bytes that contain the internal data for this solution vector
bd6639fd
MT
466 unsigned char *ExtraDataPtr()
467 {
468 if (ExtraDataLen())
469 {
25eff798 470 return &(vch.data()[HeadersOverheadSize()]);
bd6639fd
MT
471 }
472 else
473 {
474 return NULL;
475 }
476 }
477
25eff798
MT
478 // return a vector of bytes that contains the extra data for this solution vector, used for
479 // stream data typically and stored after PBaaS headers
ec1c84a0 480 void GetExtraData(std::vector<unsigned char> &dataVec)
bd6639fd 481 {
25eff798 482 int len = Descriptor().extraDataSize;
bd6639fd
MT
483
484 if (len > 0)
485 {
486 dataVec.resize(len);
25eff798 487 std::memcpy(dataVec.data(), ExtraDataPtr(), len);
bd6639fd
MT
488 }
489 else
490 {
491 dataVec.clear();
492 }
493 }
494
495 // set the extra data with a pointer to bytes and length
496 bool SetExtraData(const unsigned char *pbegin, uint32_t len)
497 {
25eff798 498 if (Version() < CActivationHeight::SOLUTION_VERUSV3 || len > ExtraDataLen())
bd6639fd
MT
499 {
500 return false;
501 }
25eff798
MT
502 auto descr = Descriptor();
503 descr.extraDataSize = len;
504 SetDescriptor(descr);
505 std::memcpy(&(vch.data()[4]), pbegin, len);
506 return true;
bd6639fd 507 }
12217420 508};
509
510#endif // BITCOIN_PRIMITIVES_SOLUTIONDATA_H
This page took 0.099291 seconds and 4 git commands to generate.