Skip to content

Commit 876d0f6

Browse files
authored
feat: override LLMQ params (#310)
* feat: override LLMQ params * fix: missing overrides * chore: remove debug output * fix: recursion in QuorumEntry constructor * refactor: rename param * style: fix too long line warning
1 parent 27a85b3 commit 876d0f6

File tree

5 files changed

+146
-105
lines changed

5 files changed

+146
-105
lines changed

lib/constants/index.js

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = {
1+
const constants = {
22
// Public key id size in bytes
33
PUBKEY_ID_SIZE: 20,
44
// Standard compact size variable, size in bytes
@@ -106,3 +106,78 @@ module.exports = {
106106
BASIC_BLS_SCHEME_VERSION: 3,
107107
BASIC_BLS_SCHEME_HASH_QUORUM_INDEX_REQUIRED_VERSION: 4,
108108
};
109+
110+
constants.LLMQ_TYPE_PARAMS= {
111+
[constants.LLMQ_TYPES.LLMQ_TYPE_50_60]: {
112+
size: 50,
113+
threshold: 30,
114+
maximumActiveQuorumsCount: 24,
115+
},
116+
[constants.LLMQ_TYPES.LLMQ_TYPE_60_75]: {
117+
size: 60,
118+
threshold: 45,
119+
maximumActiveQuorumsCount: 24,
120+
},
121+
[constants.LLMQ_TYPES.LLMQ_TYPE_400_60]: {
122+
size: 400,
123+
threshold: 240,
124+
maximumActiveQuorumsCount: 4,
125+
},
126+
[constants.LLMQ_TYPES.LLMQ_TYPE_400_85]: {
127+
size: 400,
128+
threshold: 340,
129+
maximumActiveQuorumsCount: 4,
130+
},
131+
[constants.LLMQ_TYPES.LLMQ_TYPE_100_67]: {
132+
size: 100,
133+
threshold: 67,
134+
maximumActiveQuorumsCount: 24,
135+
},
136+
[constants.LLMQ_TYPES.LLMQ_TYPE_25_67]: {
137+
size: 25,
138+
threshold: 67,
139+
maximumActiveQuorumsCount: 24,
140+
},
141+
[constants.LLMQ_TYPES.LLMQ_TYPE_LLMQ_TEST]: {
142+
size: 3,
143+
threshold: 2,
144+
maximumActiveQuorumsCount: 2,
145+
},
146+
[constants.LLMQ_TYPES.LLMQ_TYPE_LLMQ_DEVNET]: {
147+
size: 12,
148+
threshold: 6,
149+
maximumActiveQuorumsCount: 4,
150+
},
151+
[constants.LLMQ_TYPES.LLMQ_TYPE_TEST_V17]: {
152+
size: 3,
153+
threshold: 2,
154+
maximumActiveQuorumsCount: 2,
155+
},
156+
[constants.LLMQ_TYPES.LLMQ_TYPE_TEST_DIP0024]: {
157+
size: 4,
158+
threshold: 2,
159+
maximumActiveQuorumsCount: 2,
160+
},
161+
[constants.LLMQ_TYPES.LLMQ_TYPE_TEST_INSTANTSEND]: {
162+
size: 3,
163+
threshold: 2,
164+
maximumActiveQuorumsCount: 2,
165+
},
166+
[constants.LLMQ_TYPES.LLMQ_DEVNET_DIP0024]: {
167+
size: 8,
168+
threshold: 4,
169+
maximumActiveQuorumsCount: 2,
170+
},
171+
[constants.LLMQ_TYPES.LLMQ_TEST_PLATFORM]: {
172+
size: 3,
173+
threshold: 2,
174+
maximumActiveQuorumsCount: 2,
175+
},
176+
[constants.LLMQ_TYPES.LLMQ_DEVNET_PLATFORM]: {
177+
size: 12,
178+
threshold: 8,
179+
maximumActiveQuorumsCount: 4,
180+
},
181+
};
182+
183+
module.exports = constants;

lib/deterministicmnlist/QuorumEntry.js

Lines changed: 28 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const {
4343
* @class QuorumEntry
4444
* @param {string|Object|Buffer} [arg] - A Buffer, JSON string,
4545
* or Object representing a SMLQuorumEntry
46+
* @param {Object} [llmqParamsOverride] - LLMQ type override
4647
* @constructor
4748
* @property {number} version
4849
* @property {number} llmqType
@@ -57,26 +58,26 @@ const {
5758
* @property {string} quorumSig
5859
* @property {string} membersSig
5960
*/
60-
function QuorumEntry(arg) {
61+
function QuorumEntry(arg, llmqParamsOverride = {}) {
6162
if (arg) {
6263
if (arg instanceof QuorumEntry) {
6364
return arg.copy();
6465
}
6566

6667
if (BufferUtil.isBuffer(arg)) {
67-
return QuorumEntry.fromBuffer(arg);
68+
return QuorumEntry.fromBuffer(arg, llmqParamsOverride);
6869
}
6970

7071
if (_.isObject(arg)) {
71-
return QuorumEntry.fromObject(arg);
72+
return QuorumEntry.fromObject(arg, llmqParamsOverride);
7273
}
7374

7475
if (arg instanceof QuorumEntry) {
7576
return arg.copy();
7677
}
7778

7879
if (isHexString(arg)) {
79-
return QuorumEntry.fromHexString(arg);
80+
return QuorumEntry.fromHexString(arg, llmqParamsOverride);
8081
}
8182
throw new TypeError('Unrecognized argument for QuorumEntry');
8283
}
@@ -85,11 +86,13 @@ function QuorumEntry(arg) {
8586
/**
8687
* Parse buffer and returns QuorumEntry
8788
* @param {Buffer} buffer
89+
* @param {Object} [llmqParamsOverride]
8890
* @return {QuorumEntry}
8991
*/
90-
QuorumEntry.fromBuffer = function fromBuffer(buffer) {
92+
QuorumEntry.fromBuffer = function fromBuffer(buffer, llmqParamsOverride = {}) {
9193
const bufferReader = new BufferReader(buffer);
9294
const SMLQuorumEntry = new QuorumEntry();
95+
SMLQuorumEntry.llmqParamsOverride = llmqParamsOverride;
9396
SMLQuorumEntry.isVerified = false;
9497
if (buffer.length < 100) {
9598
SMLQuorumEntry.isOutdatedRPC = true;
@@ -159,10 +162,11 @@ QuorumEntry.fromBuffer = function fromBuffer(buffer) {
159162

160163
/**
161164
* @param {string} string
165+
* @param {Object} llmqParamsOverride
162166
* @return {QuorumEntry}
163167
*/
164-
QuorumEntry.fromHexString = function fromString(string) {
165-
return QuorumEntry.fromBuffer(Buffer.from(string, 'hex'));
168+
QuorumEntry.fromHexString = function fromString(string, llmqParamsOverride = {}) {
169+
return QuorumEntry.fromBuffer(Buffer.from(string, 'hex'), llmqParamsOverride);
166170
};
167171

168172
/**
@@ -232,9 +236,10 @@ QuorumEntry.prototype.toBufferForHashing = function toBufferForHashing() {
232236
/**
233237
* Create SMLQuorumEntry from an object
234238
* @param {SMLQuorumEntry} obj
239+
* @param {Object} llmqParamsOverride
235240
* @return {QuorumEntry}
236241
*/
237-
QuorumEntry.fromObject = function fromObject(obj) {
242+
QuorumEntry.fromObject = function fromObject(obj, llmqParamsOverride = {}) {
238243
const SMLQuorumEntry = new QuorumEntry();
239244
SMLQuorumEntry.isVerified = false;
240245
SMLQuorumEntry.isOutdatedRPC = false;
@@ -250,6 +255,9 @@ QuorumEntry.fromObject = function fromObject(obj) {
250255
SMLQuorumEntry.quorumVvecHash = obj.quorumVvecHash;
251256
SMLQuorumEntry.quorumSig = obj.quorumSig;
252257
SMLQuorumEntry.membersSig = obj.membersSig;
258+
259+
SMLQuorumEntry.llmqParamsOverride = llmqParamsOverride;
260+
253261
if (SMLQuorumEntry.signers === undefined) {
254262
SMLQuorumEntry.isOutdatedRPC = true;
255263
}
@@ -334,88 +342,24 @@ QuorumEntry.prototype.toObject = function toObject() {
334342
return result;
335343
};
336344

337-
QuorumEntry.getParams = function getParams(llmqType) {
338-
const params = {};
339-
switch (llmqType) {
340-
case constants.LLMQ_TYPES.LLMQ_TYPE_50_60:
341-
params.size = 50;
342-
params.threshold = 30;
343-
params.maximumActiveQuorumsCount = 24;
344-
return params;
345-
case constants.LLMQ_TYPES.LLMQ_TYPE_60_75:
346-
params.size = 60;
347-
params.threshold = 45;
348-
params.maximumActiveQuorumsCount = 32;
349-
return params;
350-
case constants.LLMQ_TYPES.LLMQ_TYPE_400_60:
351-
params.size = 400;
352-
params.threshold = 240;
353-
params.maximumActiveQuorumsCount = 4;
354-
return params;
355-
case constants.LLMQ_TYPES.LLMQ_TYPE_400_85:
356-
params.size = 400;
357-
params.threshold = 340;
358-
params.maximumActiveQuorumsCount = 4;
359-
return params;
360-
case constants.LLMQ_TYPES.LLMQ_TYPE_100_67:
361-
params.size = 100;
362-
params.threshold = 67;
363-
params.maximumActiveQuorumsCount = 24;
364-
return params;
365-
case constants.LLMQ_TYPES.LLMQ_TYPE_25_67:
366-
params.size = 25;
367-
params.threshold = 67;
368-
params.maximumActiveQuorumsCount = 24;
369-
return params;
370-
case constants.LLMQ_TYPES.LLMQ_TYPE_LLMQ_TEST:
371-
params.size = 3;
372-
params.threshold = 2;
373-
params.maximumActiveQuorumsCount = 2;
374-
return params;
375-
case constants.LLMQ_TYPES.LLMQ_TYPE_LLMQ_DEVNET:
376-
params.size = 12;
377-
params.threshold = 6;
378-
params.maximumActiveQuorumsCount = 4;
379-
return params;
380-
case constants.LLMQ_TYPES.LLMQ_TYPE_TEST_V17:
381-
params.size = 3;
382-
params.threshold = 2;
383-
params.maximumActiveQuorumsCount = 2;
384-
return params;
385-
case constants.LLMQ_TYPES.LLMQ_TYPE_TEST_DIP0024:
386-
params.size = 4;
387-
params.threshold = 2;
388-
params.maximumActiveQuorumsCount = 2;
389-
return params;
390-
case constants.LLMQ_TYPES.LLMQ_TYPE_TEST_INSTANTSEND:
391-
params.size = 3;
392-
params.threshold = 2;
393-
params.maximumActiveQuorumsCount = 2;
394-
return params;
395-
case constants.LLMQ_TYPES.LLMQ_DEVNET_DIP0024:
396-
params.size = 8;
397-
params.threshold = 4;
398-
params.maximumActiveQuorumsCount = 2;
399-
return params;
400-
case constants.LLMQ_TYPES.LLMQ_TEST_PLATFORM:
401-
params.size = 3;
402-
params.threshold = 2;
403-
params.maximumActiveQuorumsCount = 2;
404-
return params;
405-
case constants.LLMQ_TYPES.LLMQ_DEVNET_PLATFORM:
406-
params.size = 12;
407-
params.threshold = 8;
408-
params.maximumActiveQuorumsCount = 4;
409-
return params;
410-
default:
411-
throw new Error(`Invalid llmq type ${llmqType}`);
345+
QuorumEntry.getParams = function getParams(llmqType, llmqParamsOverride = {}) {
346+
let llmqParams = constants.LLMQ_TYPE_PARAMS;
347+
if (Object.keys(llmqParamsOverride).length > 0) {
348+
llmqParams = _.merge({}, constants.LLMQ_TYPE_PARAMS, llmqParamsOverride);
349+
}
350+
351+
if (!llmqParams[llmqType]) {
352+
throw new Error(`Invalid llmq type ${llmqType}`);
412353
}
354+
355+
return llmqParams[llmqType];
413356
};
357+
414358
/**
415359
* @return {number}
416360
*/
417361
QuorumEntry.prototype.getParams = function getParams() {
418-
return QuorumEntry.getParams(this.llmqType);
362+
return QuorumEntry.getParams(this.llmqType, this.llmqParamsOverride);
419363
};
420364

421365
/**

lib/deterministicmnlist/SimplifiedMNList.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ const Networks = require('../networks');
1111
const Transaction = require('../transaction');
1212
const { MASTERNODE_TYPE_HP } = require("../constants");
1313

14-
function SimplifiedMNList(simplifiedMNListDiff) {
14+
/**
15+
* @param {SimplifiedMNListDiff} simplifiedMNListDiff
16+
* @param {Object} llmqParamsOverride
17+
* @constructor
18+
*/
19+
function SimplifiedMNList(simplifiedMNListDiff = null, llmqParamsOverride = {}) {
1520
this.baseBlockHash = constants.NULL_HASH;
1621
this.blockHash = constants.NULL_HASH;
1722
/**
@@ -38,6 +43,7 @@ function SimplifiedMNList(simplifiedMNListDiff) {
3843
this.quorumsActive = false;
3944
this.cbTx = null;
4045
this.cbTxMerkleTree = null;
46+
this.llmqParamsOverride = llmqParamsOverride;
4147
if (simplifiedMNListDiff) {
4248
this.applyDiff(simplifiedMNListDiff);
4349
}
@@ -52,7 +58,11 @@ SimplifiedMNList.prototype.applyDiff = function applyDiff(
5258
simplifiedMNListDiff
5359
) {
5460
// This will copy an instance of SimplifiedMNListDiff or create a new instance
55-
const diff = new SimplifiedMNListDiff(simplifiedMNListDiff, this.network);
61+
const diff = new SimplifiedMNListDiff(
62+
simplifiedMNListDiff,
63+
this.network,
64+
this.llmqParamsOverride,
65+
);
5666

5767
// only when we apply the first diff we set the network
5868
if (!this.network) {
@@ -162,7 +172,8 @@ SimplifiedMNList.prototype.addAndMaybeRemoveQuorums =
162172
? newGroupedQuorums[quorumType].length
163173
: 0;
164174
const maxAllowedQuorumsOfType = QuorumEntry.getParams(
165-
Number(quorumType)
175+
Number(quorumType),
176+
this.llmqParamsOverride,
166177
).maximumActiveQuorumsCount;
167178

168179
if (
@@ -566,15 +577,17 @@ SimplifiedMNList.prototype.toSimplifiedMNListDiff =
566577
merkleRootQuorums: this.merkleRootQuorums,
567578
nVersion: this.nVersion,
568579
},
569-
network
580+
network,
581+
this.llmqParamsOverride,
570582
);
571583
};
572584

573585
/**
574586
* Recreates SML from json
575587
* @param {Object} smlJson
588+
* @param {Object} llmqParamsOverride
576589
*/
577-
SimplifiedMNList.fromJSON = function fromJSON(smlJson) {
590+
SimplifiedMNList.fromJSON = function fromJSON(smlJson, llmqParamsOverride = {}) {
578591
const sml = new SimplifiedMNList();
579592
sml.baseBlockHash = smlJson.baseBlockHash;
580593
sml.blockHash = smlJson.blockHash;
@@ -592,7 +605,7 @@ SimplifiedMNList.fromJSON = function fromJSON(smlJson) {
592605
(mnRecord) => new SimplifiedMNListEntry(mnRecord)
593606
);
594607
sml.quorumList = smlJson.quorumList.map(
595-
(quorumEntry) => new QuorumEntry(quorumEntry)
608+
(quorumEntry) => new QuorumEntry(quorumEntry, llmqParamsOverride),
596609
);
597610
sml.validMNs = smlJson.validMNs.map(
598611
(mnRecord) => new SimplifiedMNListEntry(mnRecord)

0 commit comments

Comments
 (0)