]>
Commit | Line | Data |
---|---|---|
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 | 15 | class CPBaaSBlockHeader; |
bd6639fd | 16 | |
12217420 | 17 | class 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 | 75 | class CBlockHeader; |
76 | ||
77 | class CPBaaSPreHeader | |
b2a98c42 | 78 | { |
85c51d62 | 79 | public: |
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 | |
113 | class CPBaaSBlockHeader | |
114 | { | |
115 | public: | |
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 | ||
186 | enum 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 | ||
192 | class 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 | 244 | class 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 | ||
388 | class 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 |