Skip to content

Commit 38efe81

Browse files
authored
feat: add method to restore sml store from json (#213)
1 parent 942368c commit 38efe81

File tree

10 files changed

+16940
-11
lines changed

10 files changed

+16940
-11
lines changed

lib/deterministicmnlist/SimplifiedMNList.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const BufferWriter = require('../encoding/bufferwriter');
22
const Hash = require('../crypto/hash');
33
const { getMerkleTree, getMerkleRoot } = require('../util/merkletree');
44
const SimplifiedMNListDiff = require('./SimplifiedMNListDiff');
5+
const QuorumEntry = require('./QuorumEntry');
6+
const SimplifiedMNListEntry = require('./SimplifiedMNListEntry');
7+
const PartialMerkleTree = require('../block/PartialMerkleTree');
58
const constants = require('../constants');
69
const Networks = require('../networks');
710
const Transaction = require('../transaction');
@@ -449,6 +452,30 @@ SimplifiedMNList.prototype.toSimplifiedMNListDiff = function toSimplifiedMNListD
449452
}, network);
450453
};
451454

455+
/**
456+
* Recreates SML from json
457+
* @param {Object} smlJson
458+
*/
459+
SimplifiedMNList.fromJSON = function fromJSON(smlJson) {
460+
const sml = new SimplifiedMNList();
461+
sml.baseBlockHash = smlJson.baseBlockHash;
462+
sml.blockHash = smlJson.blockHash;
463+
sml.merkleRootMNList = smlJson.merkleRootMNList;
464+
sml.lastDiffMerkleRootMNList = smlJson.lastDiffMerkleRootMNList;
465+
sml.lastDiffMerkleRootQuorums = smlJson.lastDiffMerkleRootQuorums;
466+
sml.quorumsActive = smlJson.quorumsActive;
467+
sml.cbTx = new Transaction(smlJson.cbTx);
468+
sml.cbTxMerkleTree = new PartialMerkleTree();
469+
sml.cbTxMerkleTree.totalTransactions = smlJson.cbTxMerkleTree.totalTransactions;
470+
sml.cbTxMerkleTree.merkleHashes = smlJson.cbTxMerkleTree.merkleHashes;
471+
sml.cbTxMerkleTree.merkleFlags = smlJson.cbTxMerkleTree.merkleFlags;
472+
sml.mnList = smlJson.mnList.map(mnRecord => new SimplifiedMNListEntry(mnRecord));
473+
sml.quorumList = smlJson.quorumList.map(quorumEntry => new QuorumEntry(quorumEntry));
474+
sml.validMNs = smlJson.validMNs.map(mnRecord => new SimplifiedMNListEntry(mnRecord));
475+
476+
return sml;
477+
};
478+
452479
/**
453480
* Deterministically selects all members of the quorum which
454481
* has started it's DKG session with the block of this MNList

lib/deterministicmnlist/SimplifiedMNListDiff.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ SimplifiedMNListDiff.fromObject = function fromObject(obj, network) {
164164
simplifiedMNListDiff.cbTx = new Transaction(obj.cbTx);
165165
// Copy array of strings
166166
simplifiedMNListDiff.deletedMNs = obj.deletedMNs.slice();
167-
simplifiedMNListDiff.mnList = obj.mnList.map(SMLEntry => new SimplifiedMNListEntry(SMLEntry, validNetwork));
167+
simplifiedMNListDiff.mnList = obj.mnList.map(
168+
SMLEntry => new SimplifiedMNListEntry(SMLEntry, validNetwork),
169+
);
168170
simplifiedMNListDiff.deletedQuorums = obj.deletedQuorums.slice();
169171
simplifiedMNListDiff.newQuorums = obj.newQuorums.map(quorumEntry => new QuorumEntry(quorumEntry));
170172
simplifiedMNListDiff.merkleRootMNList = obj.merkleRootMNList;
@@ -185,6 +187,23 @@ SimplifiedMNListDiff.fromObject = function fromObject(obj, network) {
185187
return simplifiedMNListDiff;
186188
};
187189

190+
/**
191+
* This method constructs the diff from the JSON produced by JSON.sringify.
192+
* PLEASE DON'T PASS RESULT OF .toObject() to this method!
193+
* @param {Object} diffJSON
194+
* @return {SimplifiedMNListDiff}
195+
*/
196+
SimplifiedMNListDiff.fromJSON = function fromJSON(diffJSON) {
197+
const cbTxMerkleTree = new PartialMerkleTree();
198+
cbTxMerkleTree.totalTransactions = diffJSON.cbTxMerkleTree.totalTransactions;
199+
cbTxMerkleTree.merkleHashes = diffJSON.cbTxMerkleTree.merkleHashes;
200+
cbTxMerkleTree.merkleFlags = diffJSON.cbTxMerkleTree.merkleFlags;
201+
202+
return SimplifiedMNListDiff.fromObject({
203+
...diffJSON, cbTxMerkleTree,
204+
}, Networks.get(diffJSON.network.name));
205+
};
206+
188207
SimplifiedMNListDiff.prototype.toObject = function toObject() {
189208
const obj = {};
190209
obj.baseBlockHash = this.baseBlockHash;

lib/deterministicmnlist/SimplifiedMNListStore.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ SimplifiedMNListStore.prototype.addDiff = function addDiff(diff) {
6868
}
6969

7070
if (this.diffStore.length >= this.maxDiffs - 1) {
71+
let oldestCoinbase = this.diffStore[0].diff.cbTx;
7172
this.baseSimplifiedMNList.applyDiff(this.diffStore[0].diff);
73+
if (typeof oldestCoinbase === 'string') {
74+
oldestCoinbase = new Transaction(oldestCoinbase);
75+
}
76+
this.baseHeight = oldestCoinbase.extraPayload.height;
7277
this.diffStore.shift();
7378
}
7479

@@ -127,7 +132,7 @@ SimplifiedMNListStore.prototype.getSMLbyHeight = function getSMLbyHeight(height)
127132
const diffs = this.getSMLDiffbyHeightRange(this.baseHeight, height);
128133

129134
if (diffs.length === 0) {
130-
throw new Error('unable to construct SML at this height');
135+
throw new Error(`Unable to reconstruct SML at height ${height}`);
131136
}
132137
return this.createListFromBaseAndDiffs(diffs);
133138
};
@@ -156,4 +161,22 @@ SimplifiedMNListStore.prototype.createListFromBaseAndDiffs = function createList
156161
return createdList;
157162
};
158163

164+
/**
165+
* Restores store that was recreated from JSON.stringify
166+
* @param smlStoreJSON
167+
* @return {SimplifiedMNListStore}
168+
*/
169+
SimplifiedMNListStore.fromJSON = function fromJSON(smlStoreJSON) {
170+
const baseDiff = SimplifiedMNList
171+
.fromJSON(smlStoreJSON.baseSimplifiedMNList).toSimplifiedMNListDiff();
172+
// Getting jsons of all other diffs
173+
const diffsFromFile = smlStoreJSON.diffStore
174+
.map(diff => SimplifiedMNListDiff.fromJSON(diff.diff));
175+
// Concatenating all diffs into an array
176+
const totalDiffsFromFile = [baseDiff, ...diffsFromFile];
177+
const smlStore = new SimplifiedMNListStore(totalDiffsFromFile, smlStoreJSON.options);
178+
179+
return smlStore;
180+
};
181+
159182
module.exports = SimplifiedMNListStore;

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@dashevo/dashcore-lib",
3-
"version": "0.19.17",
3+
"version": "0.19.18",
44
"description": "A pure and powerful JavaScript Dash library.",
55
"author": "Dash Core Group, Inc. <dev@dash.org>",
66
"main": "index.js",

test/deterministicmnlist/SimplifiedMNListStore.js

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@ const constants = require('../../lib/constants');
33
const SimplifiedMNListStore = require('../../lib/deterministicmnlist/SimplifiedMNListStore');
44
const SMNListFixture = require('../fixtures/mnList');
55
const Transaction = require('../../lib/transaction');
6+
const getSMLStoreJSONFixture = require('../fixtures/getSMLStoreJSON');
7+
const sml4848Json = require('../fixtures/smlstore4848_4864.json');
68

79
let smlDiffArray;
8-
9-
10+
let sml4848;
1011

1112
describe('SimplifiedMNListStore', function () {
1213
this.timeout(5000);
1314

1415
beforeEach(()=>{
1516
smlDiffArray = SMNListFixture.getChainlockDiffArray();
17+
sml4848 = SimplifiedMNListStore.fromJSON(sml4848Json);
1618
});
1719

1820
describe('constructor', function () {
@@ -101,7 +103,36 @@ describe('SimplifiedMNListStore', function () {
101103
const height = 11111;
102104
expect(function () {
103105
smlStore.getSMLbyHeight(height);
104-
}).to.throw('unable to construct SML at this height');
106+
}).to.throw('Unable to reconstruct SML at height 11111');
107+
});
108+
});
109+
describe('.fromJSON', function () {
110+
it('should restore an SML store from JSON', function () {
111+
const smlStoreJSON = getSMLStoreJSONFixture();
112+
const smlStore = SimplifiedMNListStore.fromJSON(getSMLStoreJSONFixture());
113+
const restoredSmlStoreJson = JSON.parse(JSON.stringify(smlStore));
114+
115+
expect(restoredSmlStoreJson).to.be.deep.equal(smlStoreJSON);
116+
});
117+
});
118+
describe('.addDiff', function () {
119+
it('should update baseHeight if the base diff was updated', function () {
120+
const smlStore = SimplifiedMNListStore.fromJSON(getSMLStoreJSONFixture());
121+
122+
expect(smlStore.baseHeight).to.be.equal(4838);
123+
124+
const diffAtHeight4854 = sml4848.diffStore[4].diff;
125+
const diffAtHeight4855 = sml4848.diffStore[5].diff;
126+
127+
smlStore.addDiff(diffAtHeight4854);
128+
129+
expect(smlStore.baseHeight).to.be.equal(4839);
130+
expect(smlStore.tipHeight).to.be.equal(smlStore.baseHeight + 15);
131+
132+
smlStore.addDiff(diffAtHeight4855);
133+
134+
expect(smlStore.baseHeight).to.be.equal(4840);
135+
expect(smlStore.tipHeight).to.be.equal(smlStore.baseHeight + 15);
105136
});
106137
});
107138
});

test/fixtures/getSMLStoreJSON.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const json = require('./smlstore4765_4853.json');
2+
3+
module.exports = function () {
4+
return JSON.parse(JSON.stringify(json));
5+
}

0 commit comments

Comments
 (0)