@typeberry/convert 0.2.0-a46bfc7 → 0.2.0-b525add

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.
Files changed (3) hide show
  1. package/index.js +90 -56
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -5223,7 +5223,7 @@ const asTypedNumber = (v) => v;
5223
5223
  const MAX_VALUE_U8 = 0xff;
5224
5224
  const MAX_VALUE_U16 = 0xffff;
5225
5225
  const MAX_VALUE_U32 = 0xffff_ffff;
5226
- const MAX_VALUE_U64 = 0xffffffffffffffffn;
5226
+ const numbers_MAX_VALUE_U64 = 0xffffffffffffffffn;
5227
5227
  /** Attempt to cast an input number into U8. */
5228
5228
  const tryAsU8 = (v) => {
5229
5229
  debug_check `${isU8(v)} input must have one-byte representation, got ${v}`;
@@ -5252,7 +5252,7 @@ const numbers_tryAsU64 = (x) => {
5252
5252
  return asTypedNumber(v);
5253
5253
  };
5254
5254
  /** Check if given number is a valid U64 number. */
5255
- const numbers_isU64 = (v) => (v & MAX_VALUE_U64) === v;
5255
+ const numbers_isU64 = (v) => (v & numbers_MAX_VALUE_U64) === v;
5256
5256
  /** Collate two U32 parts into one U64. */
5257
5257
  const u64FromParts = ({ lower, upper }) => {
5258
5258
  const val = (BigInt(upper) << 32n) + BigInt(lower);
@@ -18734,17 +18734,16 @@ class fetch_externalities_FetchExternalities {
18734
18734
 
18735
18735
 
18736
18736
 
18737
+
18737
18738
  class AccumulateDataItem {
18738
18739
  operands;
18739
18740
  reportsLength;
18740
- gasCost;
18741
- constructor(operands, reportsLength, gasCost) {
18741
+ constructor(operands, reportsLength) {
18742
18742
  this.operands = operands;
18743
18743
  this.reportsLength = reportsLength;
18744
- this.gasCost = gasCost;
18745
18744
  }
18746
18745
  static empty() {
18747
- return new AccumulateDataItem([], tryAsU32(0), tryAsServiceGas(0n));
18746
+ return new AccumulateDataItem([], tryAsU32(0));
18748
18747
  }
18749
18748
  }
18750
18749
  /**
@@ -18756,21 +18755,39 @@ class AccumulateDataItem {
18756
18755
  class accumulate_data_AccumulateData {
18757
18756
  reportsDataByServiceId;
18758
18757
  transfersByServiceId;
18759
- autoAccumulateServicesByServiceId;
18758
+ gasLimitByServiceId;
18760
18759
  serviceIds;
18761
18760
  constructor(reports, transfers, autoAccumulateServices) {
18762
- const { autoAccumulateServicesByServiceId, serviceIds: serviceIdsFromAutoAccumulate } = this.transformAutoAccumulateServices(autoAccumulateServices);
18763
- this.autoAccumulateServicesByServiceId = autoAccumulateServicesByServiceId;
18764
- const { reportsDataByServiceId, serviceIds: serviceIdsFromReports } = this.transformReports(reports);
18761
+ const { serviceIds: serviceIdsFromAutoAccumulate, gasLimitByServiceId: autoAccumulateGasLimitByServiceId } = this.transformAutoAccumulateServices(autoAccumulateServices);
18762
+ const { reportsDataByServiceId, serviceIds: serviceIdsFromReports, gasLimitByServiceId: reportsGasLimitByServiceId, } = this.transformReports(reports);
18765
18763
  this.reportsDataByServiceId = reportsDataByServiceId;
18766
- const { transfersByServiceId, serviceIds: serviceIdsFromTransfers } = this.transformTransfers(transfers);
18764
+ const { transfersByServiceId, serviceIds: serviceIdsFromTransfers, gasLimitByServiceId: transfersGasLimitByServiceId, } = this.transformTransfers(transfers);
18767
18765
  this.transfersByServiceId = transfersByServiceId;
18768
18766
  /**
18769
18767
  * Merge service ids from reports, auto-accumulate services and transfers.
18770
18768
  *
18771
- * https://graypaper.fluffylabs.dev/#/68eaa1f/175f01175f01?v=0.6.4
18769
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/173803174b03?v=0.7.2
18772
18770
  */
18773
18771
  this.serviceIds = this.mergeServiceIds(serviceIdsFromReports, serviceIdsFromAutoAccumulate, serviceIdsFromTransfers);
18772
+ /**
18773
+ * Merge gas limits from reports, auto-accumulate services and transfers.
18774
+ *
18775
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/182001183701?v=0.7.2
18776
+ */
18777
+ this.gasLimitByServiceId = this.mergeGasLimitByServiceId(this.serviceIds, autoAccumulateGasLimitByServiceId, reportsGasLimitByServiceId, transfersGasLimitByServiceId);
18778
+ }
18779
+ /**
18780
+ * Calculate the gas limit implied by the selected deferred-transfers, work-reports and gas-privileges.
18781
+ *
18782
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/182001183701?v=0.7.2
18783
+ */
18784
+ mergeGasLimitByServiceId(serviceIds, ...gasLimitByServiceIdMaps) {
18785
+ const gasByServiceId = new Map();
18786
+ for (const serviceId of serviceIds) {
18787
+ const { overflow, value } = sumU64(...gasLimitByServiceIdMaps.map((map) => map.get(serviceId) ?? tryAsServiceGas(0)));
18788
+ gasByServiceId.set(serviceId, tryAsServiceGas(overflow ? MAX_VALUE_U64 : value));
18789
+ }
18790
+ return gasByServiceId;
18774
18791
  }
18775
18792
  /** Merge two sets of service ids */
18776
18793
  mergeServiceIds(...sources) {
@@ -18782,50 +18799,74 @@ class accumulate_data_AccumulateData {
18782
18799
  }
18783
18800
  return Array.from(merged);
18784
18801
  }
18802
+ /**
18803
+ * Transform the list of pending transfers into:
18804
+ * - map: transfers by service id
18805
+ * - map: gas limit by service id
18806
+ * - set: service ids
18807
+ */
18785
18808
  transformTransfers(transfersToTransform) {
18786
18809
  const transfersByServiceId = new Map();
18787
18810
  const serviceIds = new Set();
18811
+ const gasLimitByServiceId = new Map();
18788
18812
  for (const transfer of transfersToTransform) {
18789
18813
  const serviceId = transfer.destination;
18790
18814
  const transfers = transfersByServiceId.get(serviceId) ?? [];
18815
+ const gas = gasLimitByServiceId.get(serviceId) ?? tryAsServiceGas(0n);
18816
+ const { value, overflow } = sumU64(gas, transfer.gas);
18817
+ gasLimitByServiceId.set(serviceId, tryAsServiceGas(overflow ? MAX_VALUE_U64 : value));
18791
18818
  transfers.push(transfer);
18792
18819
  transfersByServiceId.set(serviceId, transfers);
18793
18820
  serviceIds.add(serviceId);
18794
18821
  }
18795
- return { transfersByServiceId, serviceIds };
18822
+ return { transfersByServiceId, serviceIds, gasLimitByServiceId };
18796
18823
  }
18797
- /** Transform the list of auto-accumulate services into a map by service id. */
18824
+ /**
18825
+ * Transform the list of auto accumulate services into:
18826
+ * - map: gas limit by service id
18827
+ * - set: service ids
18828
+ */
18798
18829
  transformAutoAccumulateServices(autoAccumulateServices) {
18799
18830
  const serviceIds = new Set();
18800
- const autoAccumulateServicesByServiceId = new Map();
18831
+ const gasLimitByServiceId = new Map();
18801
18832
  for (const autoAccumulate of autoAccumulateServices) {
18802
- autoAccumulateServicesByServiceId.set(autoAccumulate.service, autoAccumulate);
18833
+ gasLimitByServiceId.set(autoAccumulate.service, autoAccumulate.gasLimit);
18803
18834
  serviceIds.add(autoAccumulate.service);
18804
18835
  }
18805
- return { autoAccumulateServicesByServiceId, serviceIds };
18836
+ return { serviceIds, gasLimitByServiceId };
18806
18837
  }
18807
18838
  /**
18808
18839
  * A function that transform reports into a list of operands and data needed for statistics (gas cost and reports length).
18809
18840
  */
18841
+ /**
18842
+ * Transform the list of reports into:
18843
+ * - map: AccumulateDataItem by service id
18844
+ * - map: gas limit by service id
18845
+ * - set: service ids
18846
+ */
18810
18847
  transformReports(reports) {
18811
18848
  const reportsDataByServiceId = new Map();
18849
+ const gasLimitByServiceId = new Map();
18812
18850
  const serviceIds = new Set();
18813
18851
  for (const report of reports) {
18814
18852
  for (const result of report.results) {
18815
18853
  const serviceId = result.serviceId;
18816
18854
  serviceIds.add(serviceId);
18817
18855
  const item = reportsDataByServiceId.get(serviceId) ?? AccumulateDataItem.empty();
18856
+ const gas = gasLimitByServiceId.get(serviceId) ?? tryAsServiceGas(0n);
18857
+ const { value, overflow } = sumU64(gas, result.gas);
18858
+ const newGas = tryAsServiceGas(overflow ? MAX_VALUE_U64 : value);
18859
+ gasLimitByServiceId.set(serviceId, newGas);
18818
18860
  /**
18819
18861
  * We count the report results and gas cost for each service to update service statistics.
18820
18862
  *
18821
- * https://graypaper.fluffylabs.dev/#/68eaa1f/171e04174a04?v=0.6.4
18863
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/180504182604?v=0.7.2
18822
18864
  */
18823
18865
  item.reportsLength = tryAsU32(item.reportsLength + 1);
18824
- item.gasCost = tryAsServiceGas(item.gasCost + result.gas);
18825
18866
  /**
18826
18867
  * Transform report into an operand
18827
18868
  *
18828
- * https://graypaper.fluffylabs.dev/#/68eaa1f/17bf02176f03?v=0.6.4
18869
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/185901181402?v=0.7.2
18829
18870
  */
18830
18871
  item.operands.push(Operand.new({
18831
18872
  gas: result.gas, // g
@@ -18839,19 +18880,7 @@ class accumulate_data_AccumulateData {
18839
18880
  reportsDataByServiceId.set(serviceId, item);
18840
18881
  }
18841
18882
  }
18842
- /**
18843
- * Add initial gas cost - it is `U(f_s, 0)` from this formula:
18844
- *
18845
- * https://graypaper.fluffylabs.dev/#/68eaa1f/17b00217b002?v=0.6.4
18846
- */
18847
- for (const serviceId of serviceIds) {
18848
- const item = reportsDataByServiceId.get(serviceId) ?? null;
18849
- const autoAccumulateService = this.autoAccumulateServicesByServiceId.get(serviceId) ?? null;
18850
- if (item !== null && autoAccumulateService !== null) {
18851
- item.gasCost = tryAsServiceGas(item.gasCost + autoAccumulateService.gasLimit);
18852
- }
18853
- }
18854
- return { reportsDataByServiceId, serviceIds };
18883
+ return { reportsDataByServiceId, serviceIds, gasLimitByServiceId };
18855
18884
  }
18856
18885
  /** Returns the list of operands for a given service id */
18857
18886
  getOperands(serviceId) {
@@ -18865,14 +18894,14 @@ class accumulate_data_AccumulateData {
18865
18894
  getReportsLength(serviceId) {
18866
18895
  return this.reportsDataByServiceId.get(serviceId)?.reportsLength ?? tryAsU32(0);
18867
18896
  }
18868
- /** Returns the gas cost for a given service id */
18869
- getGasCost(serviceId) {
18870
- return this.reportsDataByServiceId.get(serviceId)?.gasCost ?? tryAsServiceGas(0n);
18897
+ /** Returns the gas limit for a given service id */
18898
+ getGasLimit(serviceId) {
18899
+ return this.gasLimitByServiceId.get(serviceId) ?? tryAsServiceGas(0n);
18871
18900
  }
18872
18901
  /**
18873
18902
  * Returns a list of service ids that should be accumulated.
18874
18903
  *
18875
- * https://graypaper.fluffylabs.dev/#/68eaa1f/175f01175f01?v=0.6.4
18904
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/173803174a03?v=0.7.2
18876
18905
  */
18877
18906
  getServiceIds() {
18878
18907
  return this.serviceIds;
@@ -24589,6 +24618,7 @@ class pvm_executor_PvmExecutor {
24589
24618
 
24590
24619
 
24591
24620
 
24621
+
24592
24622
  const ACCUMULATION_ERROR = "duplicate service created";
24593
24623
  var PvmInvocationError;
24594
24624
  (function (PvmInvocationError) {
@@ -24789,8 +24819,15 @@ class accumulate_Accumulate {
24789
24819
  const { gasCost, state: stateAfterParallelAcc, ...rest } = await this.accumulateInParallel(accumulateData, slot, entropy, statistics, stateUpdate);
24790
24820
  const newTransfers = stateAfterParallelAcc.takeTransfers();
24791
24821
  assertEmpty(rest);
24822
+ /**
24823
+ * Gas limit from transfers is added to the next round of accumulation
24824
+ *
24825
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/172b02172b02?v=0.7.2
24826
+ */
24827
+ const transfersGas = transfers.map((t) => t.gas);
24828
+ const { value: newGasLimit, overflow } = sumU64(tryAsServiceGas(gasLimit - gasCost), ...transfersGas);
24792
24829
  // NOTE [ToDr] recursive invocation
24793
- const { accumulatedReports, gasCost: seqGasCost, state, ...seqRest } = await this.accumulateSequentially(tryAsServiceGas(gasLimit - gasCost), reportsToAccumulateSequentially, newTransfers, slot, entropy, statistics, stateAfterParallelAcc, []);
24830
+ const { accumulatedReports, gasCost: seqGasCost, state, ...seqRest } = await this.accumulateSequentially(tryAsServiceGas(overflow ? MAX_VALUE_U64 : newGasLimit), reportsToAccumulateSequentially, newTransfers, slot, entropy, statistics, stateAfterParallelAcc, []);
24794
24831
  assertEmpty(seqRest);
24795
24832
  return {
24796
24833
  accumulatedReports: tryAsU32(i + accumulatedReports),
@@ -24816,7 +24853,7 @@ class accumulate_Accumulate {
24816
24853
  for (const serviceId of serviceIds) {
24817
24854
  const checkpoint = AccumulationStateUpdate.copyFrom(currentState);
24818
24855
  const operands = accumulateData.getOperands(serviceId);
24819
- const { consumedGas, stateUpdate } = await this.accumulateSingleService(serviceId, accumulateData.getTransfers(serviceId), operands, accumulateData.getGasCost(serviceId), slot, entropy, currentState);
24856
+ const { consumedGas, stateUpdate } = await this.accumulateSingleService(serviceId, accumulateData.getTransfers(serviceId), operands, accumulateData.getGasLimit(serviceId), slot, entropy, currentState);
24820
24857
  gasCost = tryAsServiceGas(gasCost + consumedGas);
24821
24858
  // https://graypaper.fluffylabs.dev/#/ab2cdbd/193b05193b05?v=0.7.2
24822
24859
  const serviceStatistics = statistics.get(serviceId) ?? { count: tryAsU32(0), gasUsed: tryAsServiceGas(0) };
@@ -24836,7 +24873,7 @@ class accumulate_Accumulate {
24836
24873
  // Since serviceIds already contains newV, this service gets accumulated twice.
24837
24874
  // To avoid double-counting, we skip stats and gas cost tracking here.
24838
24875
  // We need this accumulation to get the correct `delegator`
24839
- const { stateUpdate } = await this.accumulateSingleService(newV, [], accumulateData.getOperands(newV), accumulateData.getGasCost(newV), slot, entropy, checkpoint);
24876
+ const { stateUpdate } = await this.accumulateSingleService(newV, [], accumulateData.getOperands(newV), accumulateData.getGasLimit(newV), slot, entropy, checkpoint);
24840
24877
  const correctV = stateUpdate?.privilegedServices?.delegator ?? this.state.privilegedServices.delegator;
24841
24878
  currentState.privilegedServices = PrivilegedServices.create({
24842
24879
  ...currentState.privilegedServices,
@@ -26374,7 +26411,6 @@ class statistics_Statistics {
26374
26411
 
26375
26412
 
26376
26413
 
26377
-
26378
26414
  class DbHeaderChain {
26379
26415
  blocks;
26380
26416
  constructor(blocks) {
@@ -26445,7 +26481,7 @@ class chain_stf_OnChain {
26445
26481
  // chapter 13: https://graypaper.fluffylabs.dev/#/68eaa1f/18b60118b601?v=0.6.4
26446
26482
  statistics;
26447
26483
  isReadyForNextEpoch = Promise.resolve(false);
26448
- constructor(chainSpec, state, blocks, hasher, pvm = PvmBackend.BuiltIn) {
26484
+ constructor(chainSpec, state, blocks, hasher, pvm) {
26449
26485
  this.chainSpec = chainSpec;
26450
26486
  this.state = state;
26451
26487
  this.hasher = hasher;
@@ -26739,7 +26775,6 @@ function state_loader_loadState(spec, blake2b, keyvals) {
26739
26775
 
26740
26776
 
26741
26777
 
26742
-
26743
26778
  class StateTransitionGenesis {
26744
26779
  static fromJson = {
26745
26780
  header: headerFromJson,
@@ -26769,7 +26804,7 @@ class StateTransition {
26769
26804
  }
26770
26805
  const keccakHasher = keccak_KeccakHasher.create();
26771
26806
  const cachedBlocks = new Map();
26772
- function loadBlocks(testPath) {
26807
+ function loadBlocks(testPath, spec) {
26773
26808
  const dir = path.dirname(testPath);
26774
26809
  const fromCache = cachedBlocks.get(dir);
26775
26810
  if (fromCache !== undefined) {
@@ -26777,20 +26812,19 @@ function loadBlocks(testPath) {
26777
26812
  }
26778
26813
  const blocks = [];
26779
26814
  for (const file of fs.readdirSync(dir)) {
26780
- if (!file.endsWith(".json")) {
26815
+ if (!file.endsWith(".bin")) {
26781
26816
  continue;
26782
26817
  }
26783
- const data = fs.readFileSync(path.join(dir, file), "utf8");
26784
- const parsed = JSON.parse(data);
26818
+ const data = fs.readFileSync(path.join(dir, file));
26785
26819
  try {
26786
- if (file.endsWith("genesis.json")) {
26787
- const content = parseFromJson(parsed, StateTransitionGenesis.fromJson);
26788
- const genesisBlock = Block.create({ header: content.header, extrinsic: emptyBlock().extrinsic });
26820
+ if (file.endsWith("genesis.bin")) {
26821
+ const genesis = Decoder.decodeObject(StateTransitionGenesis.Codec, data, spec);
26822
+ const genesisBlock = Block.create({ header: genesis.header, extrinsic: emptyBlock().extrinsic });
26789
26823
  blocks.push(genesisBlock);
26790
26824
  }
26791
26825
  else {
26792
- const content = parseFromJson(parsed, StateTransition.fromJson);
26793
- blocks.push(content.block);
26826
+ const test = Decoder.decodeObject(StateTransition.Codec, data, spec);
26827
+ blocks.push(test.block);
26794
26828
  }
26795
26829
  }
26796
26830
  catch {
@@ -26812,20 +26846,20 @@ const jamConformance070V0Spec = new ChainSpec({
26812
26846
  ...chain_spec_tinyChainSpec,
26813
26847
  maxLookupAnchorAge: numbers_tryAsU32(14_400),
26814
26848
  });
26815
- async function runStateTransition(testContent, testPath, t) {
26849
+ async function runStateTransition(testContent, testPath, t, chainSpec) {
26816
26850
  const blake2b = await Blake2b.createHasher();
26817
26851
  // a bit of a hack, but the new value for `maxLookupAnchorAge` was proposed with V1
26818
26852
  // version of the fuzzer, yet these tests were still depending on the older value.
26819
26853
  // To simplify the chain spec, we just special case this one vector here.
26820
26854
  const spec = testPath.includes("fuzz-reports/0.7.0/traces/1756548916/00000082.json")
26821
26855
  ? jamConformance070V0Spec
26822
- : tinyChainSpec;
26856
+ : chainSpec;
26823
26857
  const preState = loadState(spec, blake2b, testContent.pre_state.keyvals);
26824
26858
  const postState = loadState(spec, blake2b, testContent.post_state.keyvals);
26825
26859
  const preStateRoot = preState.backend.getRootHash(blake2b);
26826
26860
  const postStateRoot = postState.backend.getRootHash(blake2b);
26827
26861
  const blockView = blockAsView(spec, testContent.block);
26828
- const allBlocks = loadBlocks(testPath);
26862
+ const allBlocks = loadBlocks(testPath, spec);
26829
26863
  const myBlockIndex = allBlocks.findIndex(({ header }) => header.timeSlotIndex === testContent.block.header.timeSlotIndex);
26830
26864
  const previousBlocks = allBlocks.slice(0, myBlockIndex);
26831
26865
  const hasher = new TransitionHasher(spec, await keccakHasher, blake2b);
@@ -26834,7 +26868,7 @@ async function runStateTransition(testContent, testPath, t) {
26834
26868
  const headerHash = hasher.header(blockView.header.view());
26835
26869
  return new WithHash(headerHash.hash, blockView);
26836
26870
  }));
26837
- const stf = new OnChain(spec, preState, blocksDb, hasher);
26871
+ const stf = new OnChain(spec, preState, blocksDb, hasher, PvmBackend.BuiltIn);
26838
26872
  // verify that we compute the state root exactly the same.
26839
26873
  assert.deepStrictEqual(testContent.pre_state.state_root.toString(), preStateRoot.toString());
26840
26874
  assert.deepStrictEqual(testContent.post_state.state_root.toString(), postStateRoot.toString());