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