Skip to content

Commit 4ee886a

Browse files
Merge pull request #730 from qubic/develop (Release v1.276.0)
Release v1.276.0
2 parents 1c07890 + b08fadf commit 4ee886a

33 files changed

+8554
-123
lines changed

src/Qubic.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<ClInclude Include="contracts\qRWA.h" />
2828
<ClInclude Include="contracts\Qswap.h" />
2929
<ClInclude Include="contracts\RandomLottery.h" />
30+
<ClInclude Include="contracts\QDuel.h" />
3031
<ClInclude Include="contracts\SupplyWatcher.h" />
3132
<ClInclude Include="contracts\EmptyTemplate.h" />
3233
<ClInclude Include="contracts\GeneralQuorumProposal.h" />
@@ -45,6 +46,9 @@
4546
<ClInclude Include="contracts\QRaffle.h" />
4647
<ClInclude Include="contracts\QBond.h" />
4748
<ClInclude Include="contracts\QIP.h" />
49+
<ClInclude Include="contracts\SupplyWatcher_old.h" />
50+
<ClInclude Include="contracts\QReservePool.h" />
51+
<ClInclude Include="contracts\QThirtyFour.h" />
4852
<ClInclude Include="contracts\TestExampleA.h" />
4953
<ClInclude Include="contracts\TestExampleB.h" />
5054
<ClInclude Include="contracts\TestExampleC.h" />

src/Qubic.vcxproj.filters

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@
303303
<ClInclude Include="contracts\RandomLottery.h">
304304
<Filter>contracts</Filter>
305305
</ClInclude>
306+
<ClInclude Include="contracts\QReservePool.h">
307+
<Filter>contracts</Filter>
308+
</ClInclude>
309+
<ClInclude Include="contracts\QThirtyFour.h">
310+
<Filter>contracts</Filter>
311+
</ClInclude>
312+
<ClInclude Include="contracts\QDuel.h">
313+
<Filter>contracts</Filter>
314+
</ClInclude>
306315
<ClInclude Include="contract_core\pre_qpi_def.h">
307316
<Filter>contract_core</Filter>
308317
</ClInclude>
@@ -327,6 +336,9 @@
327336
<ClInclude Include="contracts\qRWA.h">
328337
<Filter>contracts</Filter>
329338
</ClInclude>
339+
<ClInclude Include="contracts\SupplyWatcher_old.h">
340+
<Filter>contracts</Filter>
341+
</ClInclude>
330342
</ItemGroup>
331343
<ItemGroup>
332344
<Filter Include="platform">
@@ -374,4 +386,4 @@
374386
<Filter>platform</Filter>
375387
</MASM>
376388
</ItemGroup>
377-
</Project>
389+
</Project>

src/assets/assets.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,8 +793,8 @@ static void assetsEndEpoch()
793793
ACQUIRE(universeLock);
794794

795795
// rebuild asset hash map, getting rid of all elements with zero shares
796-
AssetRecord* reorgAssets = (AssetRecord*)reorgBuffer;
797-
setMem(reorgAssets, ASSETS_CAPACITY * sizeof(AssetRecord), 0);
796+
AssetRecord* reorgAssets = (AssetRecord*)commonBuffers.acquireBuffer(universeSizeInBytes);
797+
setMem(reorgAssets, universeSizeInBytes, 0);
798798
for (unsigned int i = 0; i < ASSETS_CAPACITY; i++)
799799
{
800800
if (assets[i].varStruct.possession.type == POSSESSION
@@ -874,6 +874,7 @@ static void assetsEndEpoch()
874874
}
875875
}
876876
copyMem(assets, reorgAssets, ASSETS_CAPACITY * sizeof(AssetRecord));
877+
commonBuffers.releaseBuffer(reorgAssets);
877878

878879
setMem(assetChangeFlags, ASSETS_CAPACITY / 8, 0xFF);
879880

src/common_buffers.h

Lines changed: 178 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,200 @@
33
#include "platform/global_var.h"
44
#include "platform/memory_util.h"
55
#include "platform/assert.h"
6+
#include "platform/concurrency.h"
67

78
#include "network_messages/entity.h"
89
#include "network_messages/assets.h"
10+
#include "contract_core/pre_qpi_def.h"
11+
#include "contracts/math_lib.h"
912

1013

1114
constexpr unsigned long long spectrumSizeInBytes = SPECTRUM_CAPACITY * sizeof(EntityRecord);
1215
constexpr unsigned long long universeSizeInBytes = ASSETS_CAPACITY * sizeof(AssetRecord);
13-
// TODO: check that max contract state size does not exceed size of spectrum or universe
14-
constexpr unsigned long long reorgBufferSize = (spectrumSizeInBytes >= universeSizeInBytes) ? spectrumSizeInBytes : universeSizeInBytes;
16+
constexpr unsigned long long defaultCommonBuffersSize = math_lib::max(MAX_CONTRACT_STATE_SIZE, math_lib::max(spectrumSizeInBytes, universeSizeInBytes));
1517

16-
// Buffer used for reorganizing spectrum and universe hash maps, currently also used as scratchpad buffer for contracts
18+
// Buffer(s) used for:
19+
// - reorganizing spectrum and universe hash maps (tick processor)
20+
// - scratchpad buffer used internally in QPI::Collection, QPI::HashMap, QPI::HashSet,
21+
// QPI::ProposalAndVotingByShareholders
22+
// (often used in contract processor which does not run concurrently with tick processor, but now also used outside
23+
// of contracts, e.g. pendingTxsPool.add() running in request processor may trigger Collection::_rebuild() which
24+
// uses scratchpad)
25+
// - building oracle transactions in processTick() in tick processor
26+
// - calculateStableComputorIndex() in tick processor
27+
// - saving and loading of logging state
28+
// - DustBurnLogger used in increaseEnergy() in tick / contract processor
1729
// Must be large enough to fit any contract, full spectrum, and full universe!
18-
GLOBAL_VAR_DECL void* reorgBuffer GLOBAL_VAR_INIT(nullptr);
30+
class CommonBuffers
31+
{
32+
public:
33+
// Allocate common buffers. With count > 1, multiple buffers may be used concurrently. The maximum buffer size
34+
// that can be acquired is given by size.
35+
bool init(unsigned int count, unsigned long long size = defaultCommonBuffersSize)
36+
{
37+
if (!count || !size)
38+
return false;
39+
40+
// soft limit, just to detect mistakes in usage like init(sizeof(Object))
41+
ASSERT(count < 16);
42+
43+
// memory layout of buffer: sub buffer pointers | sub buffer locks | sub buffer 1 | sub buffer 2 | ...
44+
unsigned char* buffer = nullptr;
45+
const unsigned long long ptrSize = count * sizeof(unsigned char*);
46+
const unsigned long long lockSize = (count + 7) / 8;
47+
const unsigned long long bufSize = count * size;
48+
49+
if (!allocPoolWithErrorLog(L"commonBuffers", ptrSize + lockSize + bufSize, (void**)&buffer, __LINE__))
50+
{
51+
return false;
52+
}
1953

20-
static bool initCommonBuffers()
21-
{
22-
if (!allocPoolWithErrorLog(L"reorgBuffer", reorgBufferSize, (void**)&reorgBuffer, __LINE__))
54+
bufferCount = count;
55+
subBufferSize = size;
56+
subBufferPtr = (unsigned char**)buffer;
57+
subBufferLock = (volatile char*)(buffer + ptrSize);
58+
unsigned char* subBuf = buffer + ptrSize + lockSize;
59+
for (unsigned int i = 0; i < count; ++i)
60+
{
61+
subBufferPtr[i] = subBuf;
62+
subBuf += size;
63+
}
64+
65+
return true;
66+
}
67+
68+
// Free common buffers.
69+
void deinit()
2370
{
24-
return false;
71+
if (subBufferPtr)
72+
{
73+
freePool(subBufferPtr);
74+
subBufferPtr = nullptr;
75+
subBufferLock = nullptr;
76+
subBufferSize = 0;
77+
bufferCount = 0;
78+
waitingCount = 0;
79+
maxWaitingCount = 0;
80+
invalidReleaseCount = 0;
81+
}
2582
}
2683

27-
return true;
28-
}
29-
30-
static void deinitCommonBuffers()
31-
{
32-
if (reorgBuffer)
84+
// Get buffer of given size.
85+
// Returns nullptr if size is too big. Otherwise may block until buffer is available.
86+
// Does not init buffer! Buffer needs to be released with releaseBuffer() after use.
87+
void* acquireBuffer(unsigned long long size)
88+
{
89+
ASSERT(subBufferLock && subBufferPtr);
90+
#if !defined(NO_UEFI)
91+
ASSERT(size <= subBufferSize);
92+
#endif
93+
if (size > subBufferSize)
94+
return nullptr;
95+
96+
// shortcut for default case
97+
if (TRY_ACQUIRE(subBufferLock[0]))
98+
{
99+
return subBufferPtr[0];
100+
}
101+
102+
long cnt = _InterlockedIncrement(&waitingCount);
103+
if (maxWaitingCount < cnt)
104+
maxWaitingCount = cnt;
105+
106+
unsigned int i = 0;
107+
BEGIN_WAIT_WHILE(TRY_ACQUIRE(subBufferLock[i]) == false)
108+
{
109+
++i;
110+
if (i >= bufferCount)
111+
i = 0;
112+
}
113+
END_WAIT_WHILE();
114+
115+
_InterlockedDecrement(&waitingCount);
116+
117+
return subBufferPtr[i];
118+
}
119+
120+
// Release buffer that was acquired with acquireBuffer() before.
121+
void releaseBuffer(void* buffer)
122+
{
123+
ASSERT(subBufferLock && subBufferPtr && buffer);
124+
125+
// shortcut for default case
126+
if (subBufferPtr[0] == buffer)
127+
{
128+
if (subBufferLock[0])
129+
RELEASE(subBufferLock[0]);
130+
else
131+
++invalidReleaseCount;
132+
return;
133+
}
134+
135+
// find buffer
136+
unsigned int bufferIdx = 1;
137+
while (bufferIdx < bufferCount && subBufferPtr[bufferIdx] != buffer)
138+
++bufferIdx;
139+
140+
// invalid pointer passed?
141+
#if !defined(NO_UEFI)
142+
ASSERT(bufferIdx < bufferCount);
143+
ASSERT(subBufferLock[bufferIdx]);
144+
#endif
145+
if (bufferIdx >= bufferCount || !subBufferLock[bufferIdx])
146+
{
147+
++invalidReleaseCount;
148+
return;
149+
}
150+
151+
// release buffer
152+
RELEASE(subBufferLock[bufferIdx]);
153+
}
154+
155+
// Heuristics how many processors were waiting for a buffer in parallel (for deciding the count of buffers)
156+
long getMaxWaitingProcessorCount() const
157+
{
158+
return maxWaitingCount;
159+
}
160+
161+
// Counter of invalid release calls as an indicator if debugging is needed
162+
long getInvalidReleaseCount() const
33163
{
34-
freePool(reorgBuffer);
35-
reorgBuffer = nullptr;
164+
return invalidReleaseCount;
36165
}
166+
167+
// Returns number of buffers currently acquired
168+
unsigned int acquiredBuffers() const
169+
{
170+
unsigned int count = 0;
171+
for (unsigned int i = 0; i < bufferCount; ++i)
172+
if (subBufferLock[i])
173+
++count;
174+
return count;
175+
}
176+
177+
protected:
178+
unsigned char** subBufferPtr = nullptr;
179+
volatile char* subBufferLock = nullptr;
180+
unsigned long long subBufferSize = 0;
181+
unsigned int bufferCount = 0;
182+
volatile long waitingCount = 0;
183+
long maxWaitingCount = 0;
184+
long invalidReleaseCount = 0;
185+
};
186+
187+
188+
GLOBAL_VAR_DECL CommonBuffers commonBuffers;
189+
190+
191+
static void* __acquireScratchpad(unsigned long long size, bool initZero = true)
192+
{
193+
void* ptr = commonBuffers.acquireBuffer(size);
194+
if (ptr && initZero)
195+
setMem(ptr, size, 0);
196+
return ptr;
37197
}
38198

39-
static void* __scratchpad(unsigned long long sizeToMemsetZero)
199+
static void __releaseScratchpad(void* ptr)
40200
{
41-
ASSERT(sizeToMemsetZero <= reorgBufferSize);
42-
if (sizeToMemsetZero)
43-
setMem(reorgBuffer, sizeToMemsetZero, 0);
44-
return reorgBuffer;
201+
commonBuffers.releaseBuffer(ptr);
45202
}

src/contract_core/contract_def.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@
7979
#define CONTRACT_INDEX SWATCH_CONTRACT_INDEX
8080
#define CONTRACT_STATE_TYPE SWATCH
8181
#define CONTRACT_STATE2_TYPE SWATCH2
82+
#ifdef OLD_SWATCH
83+
#include "contracts/SupplyWatcher_old.h"
84+
#else
8285
#include "contracts/SupplyWatcher.h"
86+
#endif
8387

8488
#undef CONTRACT_INDEX
8589
#undef CONTRACT_STATE_TYPE
@@ -211,6 +215,54 @@
211215
#define CONTRACT_STATE2_TYPE QRWA2
212216
#include "contracts/qRWA.h"
213217

218+
#ifndef NO_QRP
219+
220+
constexpr unsigned short qrpContractIndex = CONTRACT_INDEX + 1;
221+
222+
#undef CONTRACT_INDEX
223+
#undef CONTRACT_STATE_TYPE
224+
#undef CONTRACT_STATE2_TYPE
225+
226+
#define QRP_CONTRACT_INDEX qrpContractIndex
227+
#define CONTRACT_INDEX QRP_CONTRACT_INDEX
228+
#define CONTRACT_STATE_TYPE QRP
229+
#define CONTRACT_STATE2_TYPE QRP2
230+
#include "contracts/QReservePool.h"
231+
232+
#endif // NO_QRP
233+
234+
#ifndef NO_QTF
235+
236+
constexpr unsigned short qtfContractIndex = CONTRACT_INDEX + 1;
237+
238+
#undef CONTRACT_INDEX
239+
#undef CONTRACT_STATE_TYPE
240+
#undef CONTRACT_STATE2_TYPE
241+
242+
#define QTF_CONTRACT_INDEX qtfContractIndex
243+
#define CONTRACT_INDEX QTF_CONTRACT_INDEX
244+
#define CONTRACT_STATE_TYPE QTF
245+
#define CONTRACT_STATE2_TYPE QTF2
246+
#include "contracts/QThirtyFour.h"
247+
248+
#endif // NO_QTF
249+
250+
#ifndef NO_QDUEL
251+
252+
constexpr unsigned short qduelContractIndex = CONTRACT_INDEX + 1;
253+
254+
#undef CONTRACT_INDEX
255+
#undef CONTRACT_STATE_TYPE
256+
#undef CONTRACT_STATE2_TYPE
257+
258+
#define QDUEL_CONTRACT_INDEX qduelContractIndex
259+
#define CONTRACT_INDEX QDUEL_CONTRACT_INDEX
260+
#define CONTRACT_STATE_TYPE QDUEL
261+
#define CONTRACT_STATE2_TYPE QDUEL2
262+
#include "contracts/QDuel.h"
263+
264+
#endif // NO_QDUEL
265+
214266
// new contracts should be added above this line
215267

216268
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
@@ -319,6 +371,15 @@ constexpr struct ContractDescription
319371
{"QIP", 189, 10000, sizeof(QIP)}, // proposal in epoch 187, IPO in 188, construction and first use in 189
320372
{"QRAFFLE", 192, 10000, sizeof(QRAFFLE)}, // proposal in epoch 190, IPO in 191, construction and first use in 192
321373
{"QRWA", 197, 10000, sizeof(QRWA)}, // proposal in epoch 195, IPO in 196, construction and first use in 197
374+
#ifndef NO_QRP
375+
{"QRP", 199, 10000, sizeof(IPO)}, // proposal in epoch 197, IPO in 198, construction and first use in 199
376+
#endif
377+
#ifndef NO_QTF
378+
{"QTF", 199, 10000, sizeof(QTF)}, // proposal in epoch 197, IPO in 198, construction and first use in 199
379+
#endif
380+
#ifndef NO_QDUEL
381+
{"QDUEL", 199, 10000, sizeof(QDUEL)}, // proposal in epoch 197, IPO in 198, construction and first use in 199
382+
#endif
322383
// new contracts should be added above this line
323384
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
324385
{"TESTEXA", 138, 10000, sizeof(TESTEXA)},
@@ -435,6 +496,15 @@ static void initializeContracts()
435496
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QIP);
436497
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QRAFFLE);
437498
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QRWA);
499+
#ifndef NO_QRP
500+
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QRP);
501+
#endif
502+
#ifndef NO_QTF
503+
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QTF);
504+
#endif
505+
#ifndef NO_QDUEL
506+
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QDUEL);
507+
#endif
438508
// new contracts should be added above this line
439509
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
440510
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(TESTEXA);

0 commit comments

Comments
 (0)