@typeberry/convert 0.1.3-135961b → 0.1.3-3f7b9cf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +55 -3
- package/index.js.map +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -20785,6 +20785,15 @@ var ResultValues;
|
|
|
20785
20785
|
ResultValues[ResultValues["Ok"] = 0] = "Ok";
|
|
20786
20786
|
ResultValues[ResultValues["Error"] = 1] = "Error";
|
|
20787
20787
|
})(ResultValues || (ResultValues = {}));
|
|
20788
|
+
/**
|
|
20789
|
+
* Getting a ring commitment is pretty expensive (hundreds of ms),
|
|
20790
|
+
* yet the validators do not always change.
|
|
20791
|
+
* For current benchmarks, we get a huge hit every epoch, hence
|
|
20792
|
+
* to overcome that we cache the results of getting ring commitment.
|
|
20793
|
+
* Note we can also tentatively populate this cache, before we even
|
|
20794
|
+
* reach the epoch change block.
|
|
20795
|
+
*/
|
|
20796
|
+
const ringCommitmentCache = [];
|
|
20788
20797
|
// TODO [ToDr] We export the entire object to allow mocking in tests.
|
|
20789
20798
|
// Ideally we would just export functions and figure out how to mock
|
|
20790
20799
|
// properly in ESM.
|
|
@@ -20800,9 +20809,27 @@ async function verifySeal(bandersnatch, authorKey, signature, payload, encodedUn
|
|
|
20800
20809
|
}
|
|
20801
20810
|
return result_Result.ok(bytes_Bytes.fromBlob(sealResult.subarray(1), hash_HASH_SIZE).asOpaque());
|
|
20802
20811
|
}
|
|
20803
|
-
|
|
20804
|
-
const keys = bytes_BytesBlob.blobFromParts(validators.map((x) => x.raw))
|
|
20805
|
-
|
|
20812
|
+
function getRingCommitment(bandersnatch, validators) {
|
|
20813
|
+
const keys = bytes_BytesBlob.blobFromParts(validators.map((x) => x.raw));
|
|
20814
|
+
// We currently compare the large bytes blob, but the number of entries in the cache
|
|
20815
|
+
// must be low. If the cache ever grows larger, we should rather consider hashing the keys.
|
|
20816
|
+
const MAX_CACHE_ENTRIES = 3;
|
|
20817
|
+
const cacheEntry = ringCommitmentCache.find((v) => v.keys.isEqualTo(keys));
|
|
20818
|
+
if (cacheEntry !== undefined) {
|
|
20819
|
+
return cacheEntry.value;
|
|
20820
|
+
}
|
|
20821
|
+
const value = getRingCommitmentNoCache(bandersnatch, keys);
|
|
20822
|
+
ringCommitmentCache.push({
|
|
20823
|
+
keys,
|
|
20824
|
+
value,
|
|
20825
|
+
});
|
|
20826
|
+
if (ringCommitmentCache.length > MAX_CACHE_ENTRIES) {
|
|
20827
|
+
ringCommitmentCache.shift();
|
|
20828
|
+
}
|
|
20829
|
+
return value;
|
|
20830
|
+
}
|
|
20831
|
+
async function getRingCommitmentNoCache(bandersnatch, keys) {
|
|
20832
|
+
const commitmentResult = await bandersnatch.getRingCommitment(keys.raw);
|
|
20806
20833
|
if (commitmentResult[RESULT_INDEX] === ResultValues.Error) {
|
|
20807
20834
|
return result_Result.error(null);
|
|
20808
20835
|
}
|
|
@@ -20928,6 +20955,18 @@ class safrole_Safrole {
|
|
|
20928
20955
|
}
|
|
20929
20956
|
return FixedSizeArray.new([newRandomnessAcc, ...rest], 4);
|
|
20930
20957
|
}
|
|
20958
|
+
/**
|
|
20959
|
+
* Pre-populate cache for validator keys, and especially the ring commitment.
|
|
20960
|
+
*
|
|
20961
|
+
* NOTE the function is still doing quite some work, so it should only be used
|
|
20962
|
+
* once per epoch. The optimisation relies on the fact that the `bandersnatch.getRingCommitment`
|
|
20963
|
+
* call will be cached.
|
|
20964
|
+
*/
|
|
20965
|
+
async prepareValidatorKeysForNextEpoch(postOffenders) {
|
|
20966
|
+
const stateEpoch = Math.floor(this.state.timeslot / this.chainSpec.epochLength);
|
|
20967
|
+
const nextEpochStart = (stateEpoch + 1) * this.chainSpec.epochLength;
|
|
20968
|
+
return await this.getValidatorKeys(tryAsTimeSlot(nextEpochStart), postOffenders);
|
|
20969
|
+
}
|
|
20931
20970
|
async getValidatorKeys(timeslot, postOffenders) {
|
|
20932
20971
|
/**
|
|
20933
20972
|
* Epoch is not changed so the previous state is returned
|
|
@@ -26225,6 +26264,7 @@ class chain_stf_OnChain {
|
|
|
26225
26264
|
authorization;
|
|
26226
26265
|
// chapter 13: https://graypaper.fluffylabs.dev/#/68eaa1f/18b60118b601?v=0.6.4
|
|
26227
26266
|
statistics;
|
|
26267
|
+
isReadyForNextEpoch = Promise.resolve(false);
|
|
26228
26268
|
constructor(chainSpec, state, blocks, hasher) {
|
|
26229
26269
|
this.chainSpec = chainSpec;
|
|
26230
26270
|
this.state = state;
|
|
@@ -26243,6 +26283,14 @@ class chain_stf_OnChain {
|
|
|
26243
26283
|
this.preimages = new Preimages(state);
|
|
26244
26284
|
this.authorization = new Authorization(chainSpec, state);
|
|
26245
26285
|
}
|
|
26286
|
+
/** Pre-populate things worth caching for the next epoch. */
|
|
26287
|
+
async prepareForNextEpoch() {
|
|
26288
|
+
if (await this.isReadyForNextEpoch) {
|
|
26289
|
+
return;
|
|
26290
|
+
}
|
|
26291
|
+
const ready = this.safrole.prepareValidatorKeysForNextEpoch(this.state.disputesRecords.punishSet);
|
|
26292
|
+
this.isReadyForNextEpoch = ready.then((_) => true);
|
|
26293
|
+
}
|
|
26246
26294
|
async verifySeal(timeSlot, block) {
|
|
26247
26295
|
const sealState = this.safrole.getSafroleSealState(timeSlot);
|
|
26248
26296
|
return await this.safroleSeal.verifyHeaderSeal(block.header.view(), sealState);
|
|
@@ -26251,6 +26299,10 @@ class chain_stf_OnChain {
|
|
|
26251
26299
|
const headerView = block.header.view();
|
|
26252
26300
|
const header = block.header.materialize();
|
|
26253
26301
|
const timeSlot = header.timeSlotIndex;
|
|
26302
|
+
// reset the epoch cache state
|
|
26303
|
+
if (headerView.epochMarker.view() !== null) {
|
|
26304
|
+
this.isReadyForNextEpoch = Promise.resolve(false);
|
|
26305
|
+
}
|
|
26254
26306
|
// safrole seal
|
|
26255
26307
|
let newEntropyHash;
|
|
26256
26308
|
if (omitSealVerification) {
|