-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathproposal.h
More file actions
424 lines (353 loc) · 17 KB
/
proposal.h
File metadata and controls
424 lines (353 loc) · 17 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
#pragma once
#include <stdint.h>
void gqmpropSetProposal(const char* nodeIp, int nodePort, const char* seed,
const char* proposalString,
uint32_t scheduledTickOffset,
bool forceSendingInvalidProposal);
void gqmpropClearProposal(const char* nodeIp, int nodePort, const char* seed,
uint32_t scheduledTickOffset);
void gqmpropGetProposals(const char* nodeIp, int nodePort, const char* proposalIndexString);
void gqmpropVote(const char* nodeIp, int nodePort, const char* seed,
const char* proposalIndexString,
const char* voteValueString,
uint32_t scheduledTickOffset,
bool forceSendingInvalidVote);
void gqmpropGetVote(const char* nodeIp, int nodePort, const char* proposalIndexString,
const char* voterIdentity, const char* voterSeed);
void gqmpropGetVotingResults(const char* nodeIp, int nodePort, const char* proposalIndexString);
void gqmpropGetRevenueDonationTable(const char* nodeIp, int nodePort);
void ccfSetProposal(const char* nodeIp, int nodePort, const char* seed,
const char* proposalString,
uint32_t scheduledTickOffset,
bool forceSendingInvalidProposal);
void ccfClearProposal(const char* nodeIp, int nodePort, const char* seed,
uint32_t scheduledTickOffset);
void ccfGetProposals(const char* nodeIp, int nodePort, const char* proposalIndexString);
void ccfGetSubscription(const char* nodeIp, int nodePort, const char* subscriptionDestination);
void ccfVote(const char* nodeIp, int nodePort, const char* seed,
const char* proposalIndexString,
const char* voteValueString,
uint32_t scheduledTickOffset,
bool forceSendingInvalidVote);
void ccfGetVote(const char* nodeIp, int nodePort, const char* proposalIndexString,
const char* voterIdentity, const char* voterSeed);
void ccfGetVotingResults(const char* nodeIp, int nodePort, const char* proposalIndexString);
void ccfGetLatestTransfers(const char* nodeIp, int nodePort);
void ccfGetRegularPayments(const char* nodeIp, int nodePort);
void shareholderSetProposal(const char* nodeIp, int nodePort, const char* seed,
unsigned int contractIndex,
const char* proposalString,
uint32_t scheduledTickOffset,
bool forceSendingInvalidProposal);
void shareholderClearProposal(const char* nodeIp, int nodePort, const char* seed,
unsigned int contractIndex,
uint32_t scheduledTickOffset);
void shareholderGetProposals(const char* nodeIp, int nodePort,
unsigned int contractIndex,
const char* proposalIndexString);
void shareholderGetVotingResults(const char* nodeIp, int nodePort,
unsigned int contractIndex,
const char* proposalIndexString);
void shareholderGetVote(const char* nodeIp, int nodePort,
unsigned int contractIndex,
const char* proposalIndexString,
const char* voterIdentity,
const char* voterSeed);
void shareholderVote(const char* nodeIp, int nodePort, const char* seed,
unsigned int contractIndex,
const char* proposalIndexString,
const char* voteValueString,
uint32_t scheduledTickOffset,
bool forceSendingInvalidVote);
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef int64_t sint64;
typedef uint64_t uint64;
constexpr uint16 INVALID_PROPOSAL_INDEX = 0xffff;
constexpr uint32 INVALID_VOTER_INDEX = 0xffffffff;
constexpr sint64 NO_VOTE_VALUE = 0x8000000000000000;
// Single vote for all types of proposals defined in August 2024.
// Input data for contract procedure call
struct ProposalSingleVoteDataV1
{
// Index of proposal the vote is about (can be requested with proposal voting API)
uint16 proposalIndex;
// Type of proposal, see ProposalTypes
uint16 proposalType;
// Tick when proposal has been set (to make sure that proposal version known by the voter matches the current version).
uint32 proposalTick;
// Value of vote. NO_VOTE_VALUE means no vote for every type.
// For proposals types with multiple options, 0 is no, 1 to N are the other options in order of definition in proposal.
// For scalar proposal types the value is passed directly.
sint64 voteValue;
};
static_assert(sizeof(ProposalSingleVoteDataV1) == 16, "Unexpected struct size.");
// For casting multiple votes for all types of proposals defined in August 2024.
// This makes sense for shareholder voting, where a single shareholder may own multiple shares, allowing to cast
// multiple votes. With this structs, the votes may be individually distributed to multiple options/values.
// Input data for contract procedure call, compatible with ProposalSingleVoteDataV1. That is, to cast all votes
// of a shareholder with the same value, just set element 0 of voteValues and leave/set the rest to zero (including
// the voteCounts).
struct ProposalMultiVoteDataV1
{
// Index of proposal the vote is about (can be requested with proposal voting API)
uint16 proposalIndex;
// Type of proposal, see ProposalTypes
uint16 proposalType;
// Tick when proposal has been set (to make sure that proposal version known by the voter matches the current version).
uint32 proposalTick;
// Value of vote. NO_VOTE_VALUE means no vote for every type.
// For proposals types with multiple options, 0 is no, 1 to N are the other options in order of definition in proposal.
// For scalar proposal types the value is passed directly.
sint64 voteValues[8];
// Count of votes to cast for the corresponding voteValues.
// For compatibility with ProposalSingleVoteDataV1, voteCounts.get(0) == 0 means all votes of the voter. In
// the other elements, 0 means no votes for the given value.
uint32 voteCounts[8];
};
static_assert(sizeof(ProposalMultiVoteDataV1) == 104, "Unexpected struct size.");
// Voting result summary for all types of proposals defined in August 2024.
// Output data for contract function call for getting voting results.
struct ProposalSummarizedVotingDataV1
{
// Index of proposal the vote is about (can be requested with proposal voting API)
uint16 proposalIndex;
// Count of options in proposal type (number of valid elements in optionVoteCount, 0 for scalar voting)
uint16 optionCount;
// Tick when proposal has been set (useful for checking if cached ProposalData is still up to date).
uint32 proposalTick;
// Maximal number of votes (number of voters who have the right to vote if there aren't multiple votes per voter)
uint32 totalVotesAuthorized;
// Number of total votes casted
uint32 totalVotesCasted;
// Voting results
union
{
// Number of votes for different options (0 = no change, 1 to N = yes to specific proposed value)
uint32 optionVoteCount[8];
// Scalar voting result (currently only for proposalType VariableScalarMean, mean value of all valid votes)
sint64 scalarVotingResult;
};
};
static_assert(sizeof(ProposalSummarizedVotingDataV1) == 16 + 8 * 4, "Unexpected struct size.");
// Proposal type constants and functions.
// Each proposal type is composed of a class and a number of options. As an alternative to having N options (option votes),
// some proposal classes (currently the one to set a variable) may allow to vote with a scalar value in a range defined
// by the proposal (scalar voting).
struct ProposalTypes
{
// Class of proposal type
struct Class
{
// Options without extra data. Supported options: 2 <= N <= 8.
static constexpr uint16 GeneralOptions = 0;
// Propose to transfer amount to address. Supported options: 2 <= N <= 5.
static constexpr uint16 Transfer = 0x100;
// Propose to set variable to a value. Supported options: 2 <= N <= 5; N == 0 means scalar voting.
static constexpr uint16 Variable = 0x200;
// Propose to transfer amount to address in a specific epoch. Supported options: 1 with ProposalDataV1.
static constexpr uint16 TransferInEpoch = 0x400;
};
// Options yes and no without extra data -> result is histogram of options
static constexpr uint16 YesNo = Class::GeneralOptions | 2;
// 3 options without extra data -> result is histogram of options
static constexpr uint16 ThreeOptions = Class::GeneralOptions | 3;
// 3 options without extra data -> result is histogram of options
static constexpr uint16 FourOptions = Class::GeneralOptions | 4;
// Transfer given amount to address with options yes/no
static constexpr uint16 TransferYesNo = Class::Transfer | 2;
// Transfer amount to address with two options of amounts and option "no change"
static constexpr uint16 TransferTwoAmounts = Class::Transfer | 3;
// Transfer amount to address with three options of amounts and option "no change"
static constexpr uint16 TransferThreeAmounts = Class::Transfer | 4;
// Transfer amount to address with four options of amounts and option "no change"
static constexpr uint16 TransferFourAmounts = Class::Transfer | 5;
// Set given variable to proposed value with options yes/no
static constexpr uint16 VariableYesNo = Class::Variable | 2;
// Set given variable to proposed value with two options of values and option "no change"
static constexpr uint16 VariableTwoValues = Class::Variable | 3;
// Set given variable to proposed value with three options of values and option "no change"
static constexpr uint16 VariableThreeValues = Class::Variable | 4;
// Set given variable to proposed value with four options of values and option "no change"
static constexpr uint16 VariableFourValues = Class::Variable | 5;
// Set given variable to value, allowing to vote with scalar value, voting result is mean value
static constexpr uint16 VariableScalarMean = Class::Variable | 0;
// Contruct type from class + number of options (no checking if type is valid)
static constexpr uint16 type(uint16 cls, uint16 options)
{
return cls | options;
}
// Return option count for a given proposal type (including "no change" option),
// 0 for scalar voting (no checking if type is valid).
static uint16 optionCount(uint16 proposalType)
{
return proposalType & 0x00ff;
}
// Return class of proposal type (no checking if type is valid).
static uint16 cls(uint16 proposalType)
{
return proposalType & 0xff00;
}
};
// Proposal data struct for all types of proposals defined in August 2024.
// Input data for contract procedure call, usable as ProposalDataType in ProposalVoting (persisted in contract states).
// You have to choose, whether to support scalar votes next to option votes. Scalar votes require 8x more storage in the state.
struct ProposalDataV1
{
// URL explaining proposal, zero-terminated string.
char url[256];
// Epoch, when proposal is active. For setProposal(), 0 means to clear proposal and non-zero means the current epoch.
uint16 epoch;
// Type of proposal, see ProposalTypes.
uint16 type;
// Tick when proposal has been set. Output only, overwritten in setProposal().
uint32 tick;
// Proposal payload data (for all except types with class GeneralProposal)
union Data
{
// Used if type class is Transfer
struct Transfer
{
uint8 destination[32];
sint64 amounts[4]; // N first amounts are the proposed options (non-negative, sorted without duplicates), rest zero
} transfer;
// Used if type class is TransferInEpoch
struct TransferInEpoch
{
uint8 destination[32];
sint64 amount; // non-negative
uint16 targetEpoch; // not checked by isValid()!
} transferInEpoch;
// Used if type class is Variable and type is not VariableScalarMean
struct VariableOptions
{
uint64 variable; // For identifying variable (interpreted by contract only)
sint64 values[4]; // N first amounts are proposed options sorted without duplicates, rest zero
} variableOptions;
// Used if type is VariableScalarMean
struct VariableScalar
{
uint64 variable; // For identifying variable (interpreted by contract only)
sint64 minValue; // Minimum value allowed in proposedValue and votes, must be > NO_VOTE_VALUE
sint64 maxValue; // Maximum value allowed in proposedValue and votes, must be >= minValue
sint64 proposedValue; // Needs to be in range between minValue and maxValue
static constexpr sint64 minSupportedValue = 0x8000000000000001;
static constexpr sint64 maxSupportedValue = 0x7fffffffffffffff;
} variableScalar;
} data;
};
static_assert(sizeof(ProposalDataV1) == 256 + 8 + 64, "Unexpected struct size.");
// Proposal data struct for 2-option proposals (requires less storage space).
// Input data for contract procedure call, usable as ProposalDataType in ProposalVoting
struct ProposalDataYesNo
{
// URL explaining proposal, zero-terminated string.
uint8 url[256];
// Epoch, when proposal is active. For setProposal(), 0 means to clear proposal and non-zero means the current epoch.
uint16 epoch;
// Type of proposal, see ProposalTypes.
uint16 type;
// Tick when proposal has been set. Output only, overwritten in setProposal().
uint32 tick;
// Proposal payload data (for all except types with class GeneralProposal)
union Data
{
// Used if type class is Transfer
struct Transfer
{
uint8 destination[32];
sint64 amount; // Amount of proposed option (non-negative)
} transfer;
// Used if type class is Variable and type is not VariableScalarMean
struct VariableOptions
{
uint64 variable; // For identifying variable (interpreted by contract only)
sint64 value; // Value of proposed option, rest zero
} variableOptions;
} data;
// Whether to support scalar votes next to option votes.
static constexpr bool supportScalarVotes = false;
};
static_assert(sizeof(ProposalDataYesNo) == 256 + 8 + 40, "Unexpected struct size.");
// CCF-specific structures for subscription support
struct SubscriptionParams
{
bool isSubscription;
uint8_t weeksPerPeriod;
uint32_t startEpoch;
uint32_t numberOfPeriods;
uint64_t amountPerPeriod; // Will be set from transfer proposal amount for CCF
SubscriptionParams() : isSubscription(false), weeksPerPeriod(0), startEpoch(0), numberOfPeriods(0), amountPerPeriod(0) {}
};
struct CCF_SubscriptionProposalData
{
uint8_t proposerId[32]; // ID of the proposer (for cancellation checks)
uint8_t destination[32]; // ID of the destination
uint8_t url[256]; // URL of the subscription
uint8_t weeksPerPeriod; // Number of weeks between payments (e.g., 1 for weekly, 4 for monthly)
uint8_t _padding0[1]; // Padding for alignment
uint8_t _padding1[2]; // Padding for alignment
uint32_t numberOfPeriods; // Total number of periods (e.g., 12 for 12 periods)
uint64_t amountPerPeriod; // Amount in Qubic per period
uint32_t startEpoch; // Epoch when subscription should start
};
struct CCF_SubscriptionData
{
uint8_t destination[32]; // ID of the destination (used as key, one per destination)
uint8_t url[256]; // URL of the subscription
uint8_t weeksPerPeriod; // Number of weeks between payments (e.g., 1 for weekly, 4 for monthly)
uint8_t _padding1[1]; // Padding for alignment
uint8_t _padding2[2]; // Padding for alignment
uint32_t numberOfPeriods; // Total number of periods (e.g., 12 for 12 periods)
uint64_t amountPerPeriod; // Amount in Qubic per period
uint32_t startEpoch; // Epoch when subscription started (startEpoch >= proposal approval epoch)
int32_t currentPeriod; // Current period index (0-based, 0 to numberOfPeriods-1)
};
struct CCF_GetProposal_input
{
uint8_t subscriptionDestination[32]; // Destination ID to look up active subscription (optional, can be zero)
uint16_t proposalIndex;
};
struct CCF_GetProposal_output
{
bool okay;
bool hasSubscriptionProposal; // True if this proposal has subscription proposal data
bool hasActiveSubscription; // True if an active subscription was found for the destination
uint8_t _padding0[1]; // Padding for alignment
uint8_t _padding1[4]; // Padding for alignment
uint8_t proposerPublicKey[32];
ProposalDataYesNo proposal;
CCF_SubscriptionData subscription; // Active subscription data if found
CCF_SubscriptionProposalData subscriptionProposal; // Subscription proposal data if this is a subscription proposal
};
struct CCF_SetProposal_input
{
ProposalDataYesNo proposal;
// Optional subscription data (only used if isSubscription is true)
bool isSubscription; // Set to true if this is a subscription proposal
uint8_t weeksPerPeriod; // Number of weeks between payments (e.g., 1 for weekly, 4 for monthly)
uint8_t _padding0[2]; // Padding for alignment
uint32_t startEpoch; // Epoch when subscription starts
uint64_t amountPerPeriod; // Amount per period (in Qubic)
uint32_t numberOfPeriods; // Total number of periods
};
struct CCF_SetProposal_output
{
uint16_t proposalIndex;
};
struct CCF_RegularPaymentEntry
{
uint8_t destination[32];
uint8_t url[256];
int64_t amount;
uint32_t tick;
int32_t periodIndex; // Which period this payment is for (0-based)
bool success;
uint8_t _padding0[1]; // Padding for alignment
uint8_t _padding1[2]; // Padding for alignment
};
struct CCF_RegularPayments_output
{
CCF_RegularPaymentEntry entries[128];
};