@typeberry/jam 0.0.4 → 0.0.5-0f1acee

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/importer/index.js CHANGED
@@ -9984,6 +9984,7 @@ function legacyServiceNested(serviceId, hash) {
9984
9984
  ;// CONCATENATED MODULE: ./packages/jam/state/accumulation-output.ts
9985
9985
 
9986
9986
 
9987
+
9987
9988
  /**
9988
9989
  * Single service-indexed commitment to accumulation output
9989
9990
  *
@@ -10004,6 +10005,16 @@ class AccumulationOutput {
10004
10005
  this.output = output;
10005
10006
  }
10006
10007
  }
10008
+ function accumulationOutputComparator(a, b) {
10009
+ const result = a.serviceId - b.serviceId;
10010
+ if (result < 0) {
10011
+ return Ordering.Less;
10012
+ }
10013
+ if (result > 0) {
10014
+ return Ordering.Greater;
10015
+ }
10016
+ return Ordering.Equal;
10017
+ }
10007
10018
 
10008
10019
  ;// CONCATENATED MODULE: ./packages/jam/state/assurances.ts
10009
10020
 
@@ -11109,6 +11120,7 @@ class StatisticsData {
11109
11120
 
11110
11121
 
11111
11122
 
11123
+
11112
11124
 
11113
11125
  var in_memory_state_UpdateError;
11114
11126
  (function (UpdateError) {
@@ -11512,7 +11524,7 @@ class InMemoryState extends WithDebug {
11512
11524
  validatorsManager: tryAsServiceId(0),
11513
11525
  autoAccumulateServices: [],
11514
11526
  }),
11515
- accumulationOutputLog: [],
11527
+ accumulationOutputLog: SortedArray.fromArray(accumulationOutputComparator, []),
11516
11528
  services: new Map(),
11517
11529
  });
11518
11530
  }
@@ -11711,7 +11723,7 @@ var serialize;
11711
11723
  /** C(16): https://graypaper.fluffylabs.dev/#/38c4e62/3b46033b4603?v=0.7.0 */
11712
11724
  serialize.accumulationOutputLog = {
11713
11725
  key: stateKeys.index(StateKeyIdx.Theta),
11714
- Codec: descriptors_codec.sequenceVarLen(AccumulationOutput.Codec),
11726
+ Codec: descriptors_codec.sequenceVarLen(AccumulationOutput.Codec).convert((i) => i.array, (o) => SortedArray.fromSortedArray(accumulationOutputComparator, o)),
11715
11727
  extract: (s) => s.accumulationOutputLog,
11716
11728
  };
11717
11729
  /** C(255, s): https://graypaper.fluffylabs.dev/#/85129da/383103383103?v=0.6.3 */
@@ -13383,7 +13395,6 @@ const GLOBAL_CONFIG = {
13383
13395
  */
13384
13396
  class Logger {
13385
13397
  moduleName;
13386
- fileName;
13387
13398
  config;
13388
13399
  /**
13389
13400
  * Create a new logger instance given filename and an optional module name.
@@ -13396,7 +13407,8 @@ class Logger {
13396
13407
  */
13397
13408
  static new(fileName, moduleName) {
13398
13409
  const fName = fileName ?? "unknown";
13399
- return new Logger(moduleName ?? fName, fName, GLOBAL_CONFIG);
13410
+ const module = moduleName ?? fName;
13411
+ return new Logger(module.padStart(8, " "), GLOBAL_CONFIG);
13400
13412
  }
13401
13413
  /**
13402
13414
  * Return currently configured level for given module. */
@@ -13433,9 +13445,8 @@ class Logger {
13433
13445
  const options = parseLoggerOptions(input, defaultLevel, workingDir);
13434
13446
  Logger.configureAllFromOptions(options);
13435
13447
  }
13436
- constructor(moduleName, fileName, config) {
13448
+ constructor(moduleName, config) {
13437
13449
  this.moduleName = moduleName;
13438
- this.fileName = fileName;
13439
13450
  this.config = config;
13440
13451
  }
13441
13452
  /** Log a message with `INSANE` level. */
@@ -20155,14 +20166,14 @@ function compareWithEncoding(chainSpec, error, actual, expected, codec) {
20155
20166
  if (actual === null || expected === null) {
20156
20167
  // if one of them is `null`, both need to be.
20157
20168
  if (actual !== expected) {
20158
- return result_Result.error(error, `Expected: ${expected}, got: ${actual}`);
20169
+ return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected}, got: ${actual}`);
20159
20170
  }
20160
20171
  return result_Result.ok(result_OK);
20161
20172
  }
20162
20173
  // compare the literal encoding.
20163
20174
  const encoded = encoder_Encoder.encodeObject(codec, actual, chainSpec);
20164
20175
  if (!encoded.isEqualTo(expected.encoded())) {
20165
- return result_Result.error(error, `Expected: ${expected.encoded()}, got: ${encoded}`);
20176
+ return result_Result.error(error, `${SafroleErrorCode[error]} Expected: ${expected.encoded()}, got: ${encoded}`);
20166
20177
  }
20167
20178
  return result_Result.ok(result_OK);
20168
20179
  }
@@ -20241,7 +20252,7 @@ class SafroleSeal {
20241
20252
  const index = timeSlot % keys.length;
20242
20253
  const sealingKey = keys[index];
20243
20254
  if (!sealingKey.isEqualTo(authorKey.bandersnatch)) {
20244
- return result_Result.error(SafroleSealError.InvalidValidator, `Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
20255
+ return result_Result.error(SafroleSealError.InvalidValidator, `Invalid Validator. Expected: ${sealingKey}, got: ${authorKey.bandersnatch}`);
20245
20256
  }
20246
20257
  // verify seal correctness
20247
20258
  const payload = bytes_BytesBlob.blobFromParts(JAM_FALLBACK_SEAL, entropy.raw);
@@ -20258,6 +20269,32 @@ class SafroleSeal {
20258
20269
 
20259
20270
 
20260
20271
 
20272
+ ;// CONCATENATED MODULE: ./packages/jam/transition/accumulate/accumulate-output.ts
20273
+
20274
+
20275
+
20276
+
20277
+
20278
+ class AccumulateOutput {
20279
+ async transition({ accumulationOutputLog }) {
20280
+ const rootHash = await getRootHash(accumulationOutputLog);
20281
+ return rootHash;
20282
+ }
20283
+ }
20284
+ /**
20285
+ * Returns a new root hash
20286
+ *
20287
+ * https://graypaper.fluffylabs.dev/#/38c4e62/3c9d013c9d01?v=0.7.0
20288
+ */
20289
+ async function getRootHash(yieldedRoots) {
20290
+ const keccakHasher = await KeccakHasher.create();
20291
+ const trieHasher = getKeccakTrieHasher(keccakHasher);
20292
+ const values = yieldedRoots.array.map(({ serviceId, output }) => {
20293
+ return bytes_BytesBlob.blobFromParts([numbers_u32AsLeBytes(serviceId), output.raw]);
20294
+ });
20295
+ return binaryMerkleization(values, trieHasher);
20296
+ }
20297
+
20261
20298
  ;// CONCATENATED MODULE: ./packages/jam/jam-host-calls/externalities/state-update.ts
20262
20299
 
20263
20300
 
@@ -23352,9 +23389,6 @@ class pvm_executor_PvmExecutor {
23352
23389
 
23353
23390
 
23354
23391
 
23355
-
23356
-
23357
-
23358
23392
 
23359
23393
 
23360
23394
 
@@ -23608,10 +23642,10 @@ class Accumulate {
23608
23642
  const { services, yieldedRoots, transfers, validatorsData, privilegedServices, authorizationQueues, ...stateUpdateRest } = state;
23609
23643
  assertEmpty(stateUpdateRest);
23610
23644
  const accStateUpdate = this.getAccumulationStateUpdate(accumulated, toAccumulateLater, slot, Array.from(statistics.keys()), services);
23611
- const accumulationOutput = Array.from(yieldedRoots.entries()).map(([serviceId, root]) => {
23645
+ const accumulationOutputUnsorted = Array.from(yieldedRoots.entries()).map(([serviceId, root]) => {
23612
23646
  return { serviceId, output: root.asOpaque() };
23613
23647
  });
23614
- const rootHash = await getRootHash(accumulationOutput);
23648
+ const accumulationOutput = SortedArray.fromArray(accumulationOutputComparator, accumulationOutputUnsorted);
23615
23649
  const authQueues = (() => {
23616
23650
  if (authorizationQueues.size === 0) {
23617
23651
  return {};
@@ -23623,7 +23657,6 @@ class Accumulate {
23623
23657
  return { authQueues: tryAsPerCore(updatedAuthQueues, this.chainSpec) };
23624
23658
  })();
23625
23659
  return result_Result.ok({
23626
- root: rootHash,
23627
23660
  stateUpdate: {
23628
23661
  ...accStateUpdate,
23629
23662
  ...(validatorsData === null ? {} : { designatedValidatorData: validatorsData }),
@@ -23636,20 +23669,6 @@ class Accumulate {
23636
23669
  });
23637
23670
  }
23638
23671
  }
23639
- /**
23640
- * Returns a new root hash
23641
- *
23642
- * https://graypaper.fluffylabs.dev/#/38c4e62/3c9d013c9d01?v=0.7.0
23643
- */
23644
- async function getRootHash(yieldedRoots) {
23645
- const keccakHasher = await KeccakHasher.create();
23646
- const trieHasher = getKeccakTrieHasher(keccakHasher);
23647
- const yieldedRootsSortedByServiceId = yieldedRoots.sort((a, b) => a.serviceId - b.serviceId);
23648
- const values = yieldedRootsSortedByServiceId.map(({ serviceId, output }) => {
23649
- return bytes_BytesBlob.blobFromParts([numbers_u32AsLeBytes(serviceId), output.raw]);
23650
- });
23651
- return binaryMerkleization(values, trieHasher);
23652
- }
23653
23672
 
23654
23673
  ;// CONCATENATED MODULE: ./packages/jam/transition/accumulate/deferred-transfers.ts
23655
23674
 
@@ -25045,6 +25064,7 @@ class Statistics {
25045
25064
 
25046
25065
 
25047
25066
 
25067
+
25048
25068
  class DbHeaderChain {
25049
25069
  blocks;
25050
25070
  constructor(blocks) {
@@ -25088,6 +25108,7 @@ class OnChain {
25088
25108
  assurances;
25089
25109
  // chapter 12: https://graypaper.fluffylabs.dev/#/68eaa1f/159f02159f02?v=0.6.4
25090
25110
  accumulate;
25111
+ accumulateOutput;
25091
25112
  // chapter 12.3: https://graypaper.fluffylabs.dev/#/68eaa1f/178203178203?v=0.6.4
25092
25113
  deferredTransfers;
25093
25114
  // chapter 12.4: https://graypaper.fluffylabs.dev/#/68eaa1f/18cc0018cc00?v=0.6.4
@@ -25112,6 +25133,7 @@ class OnChain {
25112
25133
  this.reports = new Reports(chainSpec, state, new DbHeaderChain(blocks));
25113
25134
  this.assurances = new Assurances(chainSpec, state);
25114
25135
  this.accumulate = new Accumulate(chainSpec, state);
25136
+ this.accumulateOutput = new AccumulateOutput();
25115
25137
  this.deferredTransfers = new DeferredTransfers(chainSpec, state);
25116
25138
  this.preimages = new Preimages(state);
25117
25139
  this.authorization = new Authorization(chainSpec, state);
@@ -25220,7 +25242,7 @@ class OnChain {
25220
25242
  if (accumulateResult.isError) {
25221
25243
  return stfError(StfErrorKind.Accumulate, accumulateResult);
25222
25244
  }
25223
- const { root: accumulateRoot, stateUpdate: accumulateUpdate, accumulationStatistics, pendingTransfers, accumulationOutputLog, ...accumulateRest } = accumulateResult.ok;
25245
+ const { stateUpdate: accumulateUpdate, accumulationStatistics, pendingTransfers, accumulationOutputLog, ...accumulateRest } = accumulateResult.ok;
25224
25246
  assertEmpty(accumulateRest);
25225
25247
  const { privilegedServices: maybePrivilegedServices, authQueues: maybeAuthorizationQueues, designatedValidatorData: maybeDesignatedValidatorData, preimages: accumulatePreimages, accumulationQueue, recentlyAccumulated, ...servicesUpdate } = accumulateUpdate;
25226
25248
  const deferredTransfersResult = await this.deferredTransfers.transition({
@@ -25234,8 +25256,9 @@ class OnChain {
25234
25256
  }
25235
25257
  const { servicesUpdate: newServicesUpdate, transferStatistics, ...deferredTransfersRest } = deferredTransfersResult.ok;
25236
25258
  assertEmpty(deferredTransfersRest);
25259
+ const accumulateRoot = await this.accumulateOutput.transition({ accumulationOutputLog });
25237
25260
  // recent history
25238
- const recentHistoryUpdate = this.recentHistory.transition({
25261
+ const recentHistoryUpdate = await this.recentHistory.transition({
25239
25262
  partial: recentHistoryPartialUpdate,
25240
25263
  headerHash,
25241
25264
  accumulateRoot,
@@ -25330,6 +25353,8 @@ class Importer {
25330
25353
  stf;
25331
25354
  // TODO [ToDr] we cannot assume state reference does not change.
25332
25355
  state;
25356
+ // Hash of the block that we have the posterior state for in `state`.
25357
+ currentHash;
25333
25358
  constructor(spec, hasher, logger, blocks, states) {
25334
25359
  this.logger = logger;
25335
25360
  this.blocks = blocks;
@@ -25342,6 +25367,7 @@ class Importer {
25342
25367
  this.verifier = new BlockVerifier(hasher, blocks);
25343
25368
  this.stf = new OnChain(spec, state, blocks, hasher, { enableParallelSealVerification: true });
25344
25369
  this.state = state;
25370
+ this.currentHash = currentBestHeaderHash;
25345
25371
  logger.info(`😎 Best time slot: ${state.timeslot} (header hash: ${currentBestHeaderHash})`);
25346
25372
  }
25347
25373
  /** Attempt to pre-verify the seal to speed up importing. */
@@ -25368,6 +25394,20 @@ class Importer {
25368
25394
  if (hash.isError) {
25369
25395
  return importerError(ImporterErrorKind.Verifier, hash);
25370
25396
  }
25397
+ // TODO [ToDr] This is incomplete/temporary fork support!
25398
+ const parentHash = block.header.view().parentHeaderHash.materialize();
25399
+ if (!this.currentHash.isEqualTo(parentHash)) {
25400
+ const state = this.states.getState(parentHash);
25401
+ if (state === null) {
25402
+ const e = result_Result.error(BlockVerifierError.StateRootNotFound);
25403
+ if (!e.isError) {
25404
+ throw new Error("unreachable, just adding to make compiler happy");
25405
+ }
25406
+ return importerError(ImporterErrorKind.Verifier, e);
25407
+ }
25408
+ this.state.updateBackend(state?.backend);
25409
+ this.currentHash = parentHash;
25410
+ }
25371
25411
  const timeSlot = block.header.view().timeSlotIndex.materialize();
25372
25412
  const headerHash = hash.ok;
25373
25413
  logger.log(`🧱 Verified block: Got hash ${headerHash} for block at slot ${timeSlot}.`);
@@ -25392,6 +25432,7 @@ class Importer {
25392
25432
  // TODO [ToDr] This is a temporary measure. We should rather read
25393
25433
  // the state of a parent block to support forks and create a fresh STF.
25394
25434
  this.state.updateBackend(newState.backend);
25435
+ this.currentHash = headerHash;
25395
25436
  logger.log(timerState());
25396
25437
  // insert new state and the block to DB.
25397
25438
  const timerDb = measure("import:db");
@@ -25697,7 +25738,7 @@ class ImporterReady extends State {
25697
25738
  const timeSlot = headerView.timeSlotIndex.materialize();
25698
25739
  let response;
25699
25740
  try {
25700
- const res = await this.importer.importBlock(blockView, null);
25741
+ const res = await this.importer.importBlock(blockView, null, config.omitSealVerification);
25701
25742
  if (res.isOk) {
25702
25743
  state_machine_logger.info(`🧊 Best block: #${timeSlot} (${res.ok.hash})`);
25703
25744
  response = result_Result.ok(this.importer.getBestStateRootHash() ?? bytes_Bytes.zero(hash_HASH_SIZE).asOpaque());
@@ -25803,7 +25844,7 @@ async function main(channel) {
25803
25844
  importer_logger.trace(`🧊 Already queued block: #${details.ok.data.timeSlot}.`);
25804
25845
  return;
25805
25846
  }
25806
- importer_logger.log(`🧊 Queued block: #${details.ok.data.timeSlot}`);
25847
+ importer_logger.log(`🧊 Queued block: #${details.ok.data.timeSlot} (skip seal: ${config.omitSealVerification})`);
25807
25848
  if (isProcessing) {
25808
25849
  return;
25809
25850
  }