@typeberry/convert 0.1.2-ced735c9 → 0.1.3-135961b

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 +462 -290
  2. package/index.js.map +1 -1
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -4695,8 +4695,8 @@ function print(level, levelAndName, strings, data) {
4695
4695
  return;
4696
4696
  }
4697
4697
  const lvlText = Level[level].padEnd(5);
4698
- const val = strings.map((v, idx) => `${v}${data[idx]}`);
4699
- const msg = `${lvlText} [${levelAndName[1]}] ${val}`;
4698
+ const val = strings.map((v, idx) => `${v}${idx < data.length ? data[idx] : ""}`);
4699
+ const msg = `${lvlText} [${levelAndName[1]}] ${val.join("")}`;
4700
4700
  if (level === Level.WARN) {
4701
4701
  console.warn(msg);
4702
4702
  }
@@ -5511,7 +5511,7 @@ function isResult(x) {
5511
5511
  var minimist = __nccwpck_require__(595);
5512
5512
  var minimist_default = /*#__PURE__*/__nccwpck_require__.n(minimist);
5513
5513
  ;// CONCATENATED MODULE: ./bin/convert/package.json
5514
- const package_namespaceObject = {"rE":"0.1.2"};
5514
+ const package_namespaceObject = {"rE":"0.1.3"};
5515
5515
  ;// CONCATENATED MODULE: ./packages/core/bytes/bitvec.ts
5516
5516
 
5517
5517
  /**
@@ -6867,13 +6867,15 @@ function validateLength(range, length, context) {
6867
6867
 
6868
6868
  /** A caching wrapper for either object or sequence item. */
6869
6869
  class ViewField {
6870
+ name;
6870
6871
  getView;
6871
6872
  getValue;
6872
6873
  getEncoded;
6873
6874
  cachedValue;
6874
6875
  cachedView;
6875
6876
  cachedBlob;
6876
- constructor(getView, getValue, getEncoded) {
6877
+ constructor(name, getView, getValue, getEncoded) {
6878
+ this.name = name;
6877
6879
  this.getView = getView;
6878
6880
  this.getValue = getValue;
6879
6881
  this.getEncoded = getEncoded;
@@ -6899,6 +6901,9 @@ class ViewField {
6899
6901
  }
6900
6902
  return this.cachedBlob;
6901
6903
  }
6904
+ toString() {
6905
+ return `ViewField<${this.name}>`;
6906
+ }
6902
6907
  }
6903
6908
  /**
6904
6909
  * A base class for all the lazy views.
@@ -6973,7 +6978,7 @@ class ObjectView {
6973
6978
  const fieldDecoder = skipper.decoder.clone();
6974
6979
  const field = this.descriptorsKeys[i];
6975
6980
  const type = this.descriptors[field];
6976
- lastItem = new ViewField(() => type.View.decode(fieldDecoder.clone()), () => type.decode(fieldDecoder.clone()), () => type.skipEncoded(fieldDecoder.clone()));
6981
+ lastItem = new ViewField(`${this.toString()}.${String(field)}`, () => type.View.decode(fieldDecoder.clone()), () => type.decode(fieldDecoder.clone()), () => type.skipEncoded(fieldDecoder.clone()));
6977
6982
  // skip the field
6978
6983
  type.skip(skipper);
6979
6984
  // cache data
@@ -6985,6 +6990,9 @@ class ObjectView {
6985
6990
  }
6986
6991
  return lastItem;
6987
6992
  }
6993
+ toString() {
6994
+ return `View<${this.materializedConstructor.name}>(cache: ${this.cache.size})`;
6995
+ }
6988
6996
  }
6989
6997
  /**
6990
6998
  * A lazy-evaluated decoder of a sequence.
@@ -7073,7 +7081,7 @@ class SequenceView {
7073
7081
  // create new cached prop
7074
7082
  const fieldDecoder = skipper.decoder.clone();
7075
7083
  const type = this.descriptor;
7076
- lastItem = new ViewField(() => type.View.decode(fieldDecoder.clone()), () => type.decode(fieldDecoder.clone()), () => type.skipEncoded(fieldDecoder.clone()));
7084
+ lastItem = new ViewField(`${this.toString()}[${index}]`, () => type.View.decode(fieldDecoder.clone()), () => type.decode(fieldDecoder.clone()), () => type.skipEncoded(fieldDecoder.clone()));
7077
7085
  // skip the field
7078
7086
  type.skip(skipper);
7079
7087
  // cache data
@@ -7085,6 +7093,9 @@ class SequenceView {
7085
7093
  }
7086
7094
  return lastItem;
7087
7095
  }
7096
+ toString() {
7097
+ return `SequenceView<${this.descriptor.name}>(cache: ${this.cache.size})`;
7098
+ }
7088
7099
  }
7089
7100
 
7090
7101
  ;// CONCATENATED MODULE: ./packages/core/codec/descriptors.ts
@@ -11498,15 +11509,12 @@ function loadConfig(configPath) {
11498
11509
 
11499
11510
 
11500
11511
 
11501
- ;// CONCATENATED MODULE: ./packages/extensions/ipc/fuzz/v0/types.ts
11512
+ ;// CONCATENATED MODULE: ./packages/jam/fuzz-proto/v1/types.ts
11502
11513
 
11503
11514
 
11504
11515
 
11505
11516
 
11506
11517
 
11507
- /**
11508
- * Reference: https://github.com/davxy/jam-conformance/blob/7c6a371a966c6446564f91676e7a2afdec5fa3da/fuzz-proto/fuzz.asn
11509
- */
11510
11518
  /**
11511
11519
  * Version ::= SEQUENCE {
11512
11520
  * major INTEGER (0..255),
@@ -11547,190 +11555,17 @@ class Version extends WithDebug {
11547
11555
  this.patch = patch;
11548
11556
  }
11549
11557
  }
11550
- /**
11551
- * PeerInfo ::= SEQUENCE {
11552
- * name UTF8String,
11553
- * app-version Version,
11554
- * jam-version Version
11555
- * }
11556
- */
11557
- class PeerInfo extends WithDebug {
11558
- name;
11559
- appVersion;
11560
- jamVersion;
11561
- static Codec = descriptors_codec.Class(PeerInfo, {
11562
- name: descriptors_codec.string,
11563
- appVersion: Version.Codec,
11564
- jamVersion: Version.Codec,
11565
- });
11566
- static create({ name, appVersion, jamVersion }) {
11567
- return new PeerInfo(name, appVersion, jamVersion);
11568
- }
11569
- constructor(name, appVersion, jamVersion) {
11570
- super();
11571
- this.name = name;
11572
- this.appVersion = appVersion;
11573
- this.jamVersion = jamVersion;
11574
- }
11575
- }
11576
- /**
11577
- * KeyValue ::= SEQUENCE {
11578
- * key TrieKey,
11579
- * value OCTET STRING
11580
- * }
11581
- */
11582
- class KeyValue extends WithDebug {
11583
- key;
11584
- value;
11585
- static Codec = descriptors_codec.Class(KeyValue, {
11586
- key: descriptors_codec.bytes(TRUNCATED_HASH_SIZE),
11587
- value: descriptors_codec.blob,
11588
- });
11589
- static create({ key, value }) {
11590
- return new KeyValue(key, value);
11591
- }
11592
- constructor(key, value) {
11593
- super();
11594
- this.key = key;
11595
- this.value = value;
11596
- }
11597
- }
11598
- /** State ::= SEQUENCE OF KeyValue */
11599
- const stateCodec = descriptors_codec.sequenceVarLen(KeyValue.Codec);
11600
- /**
11601
- * SetState ::= SEQUENCE {
11602
- * header Header,
11603
- * state State
11604
- * }
11605
- */
11606
- class SetState extends WithDebug {
11607
- header;
11608
- state;
11609
- static Codec = descriptors_codec.Class(SetState, {
11610
- header: header_Header.Codec,
11611
- state: descriptors_codec.sequenceVarLen(KeyValue.Codec),
11612
- });
11613
- static create({ header, state }) {
11614
- return new SetState(header, state);
11615
- }
11616
- constructor(header, state) {
11617
- super();
11618
- this.header = header;
11619
- this.state = state;
11620
- }
11621
- }
11622
- /** GetState ::= HeaderHash */
11623
- const getStateCodec = descriptors_codec.bytes(hash_HASH_SIZE).asOpaque();
11624
- /** StateRoot ::= StateRootHash */
11625
- const stateRootCodec = descriptors_codec.bytes(hash_HASH_SIZE).asOpaque();
11626
- /** Message choice type tags */
11627
- var MessageType;
11628
- (function (MessageType) {
11629
- MessageType[MessageType["PeerInfo"] = 0] = "PeerInfo";
11630
- MessageType[MessageType["ImportBlock"] = 1] = "ImportBlock";
11631
- MessageType[MessageType["SetState"] = 2] = "SetState";
11632
- MessageType[MessageType["GetState"] = 3] = "GetState";
11633
- MessageType[MessageType["State"] = 4] = "State";
11634
- MessageType[MessageType["StateRoot"] = 5] = "StateRoot";
11635
- })(MessageType || (MessageType = {}));
11636
- /**
11637
- * Message ::= CHOICE {
11638
- * peer-info [0] PeerInfo,
11639
- * import-block [1] ImportBlock,
11640
- * set-state [2] SetState,
11641
- * get-state [3] GetState,
11642
- * state [4] State,
11643
- * state-root [5] StateRoot
11644
- * }
11645
- */
11646
- const messageCodec = descriptors_codec.custom({
11647
- name: "Message",
11648
- sizeHint: { bytes: 1, isExact: false },
11649
- }, (e, msg) => {
11650
- e.i8(msg.type);
11651
- switch (msg.type) {
11652
- case MessageType.PeerInfo:
11653
- PeerInfo.Codec.encode(e, msg.value);
11654
- break;
11655
- case MessageType.ImportBlock:
11656
- block_Block.Codec.View.encode(e, msg.value);
11657
- break;
11658
- case MessageType.SetState:
11659
- SetState.Codec.encode(e, msg.value);
11660
- break;
11661
- case MessageType.GetState:
11662
- getStateCodec.encode(e, msg.value);
11663
- break;
11664
- case MessageType.State:
11665
- stateCodec.encode(e, msg.value);
11666
- break;
11667
- case MessageType.StateRoot:
11668
- stateRootCodec.encode(e, msg.value);
11669
- break;
11670
- default:
11671
- throw new Error(`Unknown message type: ${msg}`);
11672
- }
11673
- }, (d) => {
11674
- const type = d.u8();
11675
- switch (type) {
11676
- case MessageType.PeerInfo:
11677
- return { type: MessageType.PeerInfo, value: PeerInfo.Codec.decode(d) };
11678
- case MessageType.ImportBlock:
11679
- return { type: MessageType.ImportBlock, value: block_Block.Codec.View.decode(d) };
11680
- case MessageType.SetState:
11681
- return { type: MessageType.SetState, value: SetState.Codec.decode(d) };
11682
- case MessageType.GetState:
11683
- return { type: MessageType.GetState, value: getStateCodec.decode(d) };
11684
- case MessageType.State:
11685
- return { type: MessageType.State, value: stateCodec.decode(d) };
11686
- case MessageType.StateRoot:
11687
- return { type: MessageType.StateRoot, value: stateRootCodec.decode(d) };
11688
- default:
11689
- throw new Error(`Unknown message type: ${type}`);
11690
- }
11691
- }, (s) => {
11692
- const type = s.decoder.u8();
11693
- switch (type) {
11694
- case MessageType.PeerInfo:
11695
- PeerInfo.Codec.View.skip(s);
11696
- break;
11697
- case MessageType.ImportBlock:
11698
- block_Block.Codec.View.skip(s);
11699
- break;
11700
- case MessageType.SetState:
11701
- SetState.Codec.View.skip(s);
11702
- break;
11703
- case MessageType.GetState:
11704
- getStateCodec.View.skip(s);
11705
- break;
11706
- case MessageType.State:
11707
- stateCodec.View.skip(s);
11708
- break;
11709
- case MessageType.StateRoot:
11710
- stateRootCodec.View.skip(s);
11711
- break;
11712
- default:
11713
- throw new Error(`Unknown message type: ${type}`);
11714
- }
11715
- });
11716
-
11717
- ;// CONCATENATED MODULE: ./packages/extensions/ipc/fuzz/v1/types.ts
11718
-
11719
-
11720
-
11721
-
11722
-
11723
11558
  /**
11724
11559
  * Fuzzer Protocol V1
11725
11560
  * Reference: https://github.com/davxy/jam-conformance/blob/main/fuzz-proto/fuzz.asn
11726
11561
  */
11727
11562
  // Feature bit constants
11728
- var Features;
11563
+ var types_Features;
11729
11564
  (function (Features) {
11730
11565
  Features[Features["Ancestry"] = 1] = "Ancestry";
11731
11566
  Features[Features["Fork"] = 2] = "Fork";
11732
11567
  Features[Features["Reserved"] = 2147483648] = "Reserved";
11733
- })(Features || (Features = {}));
11568
+ })(types_Features || (types_Features = {}));
11734
11569
  /**
11735
11570
  * PeerInfo ::= SEQUENCE {
11736
11571
  * fuzz-version U8,
@@ -11740,13 +11575,13 @@ var Features;
11740
11575
  * name UTF8String
11741
11576
  * }
11742
11577
  */
11743
- class types_PeerInfo extends WithDebug {
11578
+ class PeerInfo extends WithDebug {
11744
11579
  fuzzVersion;
11745
11580
  features;
11746
11581
  jamVersion;
11747
11582
  appVersion;
11748
11583
  name;
11749
- static Codec = descriptors_codec.Class(types_PeerInfo, {
11584
+ static Codec = descriptors_codec.Class(PeerInfo, {
11750
11585
  fuzzVersion: descriptors_codec.u8,
11751
11586
  features: descriptors_codec.u32,
11752
11587
  jamVersion: Version.Codec,
@@ -11754,7 +11589,7 @@ class types_PeerInfo extends WithDebug {
11754
11589
  name: descriptors_codec.string,
11755
11590
  });
11756
11591
  static create({ fuzzVersion, features, appVersion, jamVersion, name }) {
11757
- return new types_PeerInfo(fuzzVersion, features, jamVersion, appVersion, name);
11592
+ return new PeerInfo(fuzzVersion, features, jamVersion, appVersion, name);
11758
11593
  }
11759
11594
  constructor(fuzzVersion, features, jamVersion, appVersion, name) {
11760
11595
  super();
@@ -11787,6 +11622,30 @@ class AncestryItem extends WithDebug {
11787
11622
  this.headerHash = headerHash;
11788
11623
  }
11789
11624
  }
11625
+ /**
11626
+ * KeyValue ::= SEQUENCE {
11627
+ * key TrieKey,
11628
+ * value OCTET STRING
11629
+ * }
11630
+ */
11631
+ class KeyValue extends WithDebug {
11632
+ key;
11633
+ value;
11634
+ static Codec = descriptors_codec.Class(KeyValue, {
11635
+ key: descriptors_codec.bytes(TRUNCATED_HASH_SIZE),
11636
+ value: descriptors_codec.blob,
11637
+ });
11638
+ static create({ key, value }) {
11639
+ return new KeyValue(key, value);
11640
+ }
11641
+ constructor(key, value) {
11642
+ super();
11643
+ this.key = key;
11644
+ this.value = value;
11645
+ }
11646
+ }
11647
+ /** State ::= SEQUENCE OF KeyValue */
11648
+ const stateCodec = descriptors_codec.sequenceVarLen(KeyValue.Codec);
11790
11649
  /**
11791
11650
  * Ancestry ::= SEQUENCE (SIZE(0..24)) OF AncestryItem
11792
11651
  * Empty when `feature-ancestry` is not supported by both parties
@@ -11822,9 +11681,9 @@ class Initialize extends WithDebug {
11822
11681
  }
11823
11682
  }
11824
11683
  /** GetState ::= HeaderHash */
11825
- const types_getStateCodec = descriptors_codec.bytes(hash_HASH_SIZE).asOpaque();
11684
+ const getStateCodec = descriptors_codec.bytes(hash_HASH_SIZE).asOpaque();
11826
11685
  /** StateRoot ::= StateRootHash */
11827
- const types_stateRootCodec = descriptors_codec.bytes(hash_HASH_SIZE).asOpaque();
11686
+ const stateRootCodec = descriptors_codec.bytes(hash_HASH_SIZE).asOpaque();
11828
11687
  /** Error ::= UTF8String */
11829
11688
  class ErrorMessage extends WithDebug {
11830
11689
  message;
@@ -11868,19 +11727,19 @@ const types_messageCodec = descriptors_codec.custom({
11868
11727
  e.i8(msg.type);
11869
11728
  switch (msg.type) {
11870
11729
  case types_MessageType.PeerInfo:
11871
- types_PeerInfo.Codec.encode(e, msg.value);
11730
+ PeerInfo.Codec.encode(e, msg.value);
11872
11731
  break;
11873
11732
  case types_MessageType.Initialize:
11874
11733
  Initialize.Codec.encode(e, msg.value);
11875
11734
  break;
11876
11735
  case types_MessageType.StateRoot:
11877
- types_stateRootCodec.encode(e, msg.value);
11736
+ stateRootCodec.encode(e, msg.value);
11878
11737
  break;
11879
11738
  case types_MessageType.ImportBlock:
11880
11739
  block_Block.Codec.View.encode(e, msg.value);
11881
11740
  break;
11882
11741
  case types_MessageType.GetState:
11883
- types_getStateCodec.encode(e, msg.value);
11742
+ getStateCodec.encode(e, msg.value);
11884
11743
  break;
11885
11744
  case types_MessageType.State:
11886
11745
  stateCodec.encode(e, msg.value);
@@ -11895,15 +11754,15 @@ const types_messageCodec = descriptors_codec.custom({
11895
11754
  const type = d.u8();
11896
11755
  switch (type) {
11897
11756
  case types_MessageType.PeerInfo:
11898
- return { type: types_MessageType.PeerInfo, value: types_PeerInfo.Codec.decode(d) };
11757
+ return { type: types_MessageType.PeerInfo, value: PeerInfo.Codec.decode(d) };
11899
11758
  case types_MessageType.Initialize:
11900
11759
  return { type: types_MessageType.Initialize, value: Initialize.Codec.decode(d) };
11901
11760
  case types_MessageType.StateRoot:
11902
- return { type: types_MessageType.StateRoot, value: types_stateRootCodec.decode(d) };
11761
+ return { type: types_MessageType.StateRoot, value: stateRootCodec.decode(d) };
11903
11762
  case types_MessageType.ImportBlock:
11904
11763
  return { type: types_MessageType.ImportBlock, value: block_Block.Codec.View.decode(d) };
11905
11764
  case types_MessageType.GetState:
11906
- return { type: types_MessageType.GetState, value: types_getStateCodec.decode(d) };
11765
+ return { type: types_MessageType.GetState, value: getStateCodec.decode(d) };
11907
11766
  case types_MessageType.State:
11908
11767
  return { type: types_MessageType.State, value: stateCodec.decode(d) };
11909
11768
  case types_MessageType.Error:
@@ -11915,19 +11774,19 @@ const types_messageCodec = descriptors_codec.custom({
11915
11774
  const type = s.decoder.u8();
11916
11775
  switch (type) {
11917
11776
  case types_MessageType.PeerInfo:
11918
- types_PeerInfo.Codec.View.skip(s);
11777
+ PeerInfo.Codec.View.skip(s);
11919
11778
  break;
11920
11779
  case types_MessageType.Initialize:
11921
11780
  Initialize.Codec.View.skip(s);
11922
11781
  break;
11923
11782
  case types_MessageType.StateRoot:
11924
- types_stateRootCodec.View.skip(s);
11783
+ stateRootCodec.View.skip(s);
11925
11784
  break;
11926
11785
  case types_MessageType.ImportBlock:
11927
11786
  block_Block.Codec.View.skip(s);
11928
11787
  break;
11929
11788
  case types_MessageType.GetState:
11930
- types_getStateCodec.View.skip(s);
11789
+ getStateCodec.View.skip(s);
11931
11790
  break;
11932
11791
  case types_MessageType.State:
11933
11792
  stateCodec.View.skip(s);
@@ -11940,6 +11799,145 @@ const types_messageCodec = descriptors_codec.custom({
11940
11799
  }
11941
11800
  });
11942
11801
 
11802
+ ;// CONCATENATED MODULE: ./packages/jam/fuzz-proto/v1/handler.ts
11803
+
11804
+
11805
+
11806
+
11807
+ const handler_logger = Logger.new(import.meta.filename, "ext-ipc-fuzz-v1");
11808
+ class FuzzTarget {
11809
+ msgHandler;
11810
+ sender;
11811
+ spec;
11812
+ sessionFeatures = 0;
11813
+ constructor(msgHandler, sender, spec) {
11814
+ this.msgHandler = msgHandler;
11815
+ this.sender = sender;
11816
+ this.spec = spec;
11817
+ }
11818
+ async onSocketMessage(msg) {
11819
+ // attempt to decode the messsage
11820
+ try {
11821
+ const message = Decoder.decodeObject(messageCodec, msg, this.spec);
11822
+ handler_logger.log `[${message.type}] incoming message`;
11823
+ await this.processAndRespond(message);
11824
+ }
11825
+ catch (e) {
11826
+ handler_logger.error `Error while processing fuzz v1 message: ${e}`;
11827
+ handler_logger.error `${e}`;
11828
+ if (e instanceof Error) {
11829
+ handler_logger.error `${e.stack ?? ""}`;
11830
+ }
11831
+ this.sender.close();
11832
+ }
11833
+ }
11834
+ async processAndRespond(message) {
11835
+ let response = null;
11836
+ switch (message.type) {
11837
+ case MessageType.PeerInfo: {
11838
+ // only support V1
11839
+ if (message.value.fuzzVersion !== 1) {
11840
+ handler_logger.warn `Unsupported fuzzer protocol version: ${message.value.fuzzVersion}. Closing`;
11841
+ this.sender.close();
11842
+ return;
11843
+ }
11844
+ // Handle handshake
11845
+ const ourPeerInfo = await this.msgHandler.getPeerInfo(message.value);
11846
+ // Calculate session features (intersection of both peer features)
11847
+ this.sessionFeatures = message.value.features & ourPeerInfo.features;
11848
+ handler_logger.info `Handshake completed. Shared features: 0b${this.sessionFeatures.toString(2)}`;
11849
+ handler_logger.log `Feature ancestry: ${(this.sessionFeatures & Features.Ancestry) !== 0}`;
11850
+ handler_logger.log `Feature fork: ${(this.sessionFeatures & Features.Fork) !== 0}`;
11851
+ response = {
11852
+ type: MessageType.PeerInfo,
11853
+ value: ourPeerInfo,
11854
+ };
11855
+ break;
11856
+ }
11857
+ case MessageType.Initialize: {
11858
+ const stateRoot = await this.msgHandler.initialize(message.value);
11859
+ response = {
11860
+ type: MessageType.StateRoot,
11861
+ value: stateRoot,
11862
+ };
11863
+ break;
11864
+ }
11865
+ case MessageType.ImportBlock: {
11866
+ const result = await this.msgHandler.importBlock(message.value);
11867
+ if (result.isOk) {
11868
+ response = {
11869
+ type: MessageType.StateRoot,
11870
+ value: result.ok,
11871
+ };
11872
+ }
11873
+ else {
11874
+ response = {
11875
+ type: MessageType.Error,
11876
+ value: result.error,
11877
+ };
11878
+ }
11879
+ break;
11880
+ }
11881
+ case MessageType.GetState: {
11882
+ const state = await this.msgHandler.getSerializedState(message.value);
11883
+ response = {
11884
+ type: MessageType.State,
11885
+ value: state,
11886
+ };
11887
+ break;
11888
+ }
11889
+ case MessageType.StateRoot: {
11890
+ handler_logger.log `--> Received unexpected 'StateRoot' message from the fuzzer. Closing.`;
11891
+ this.sender.close();
11892
+ return;
11893
+ }
11894
+ case MessageType.State: {
11895
+ handler_logger.log `--> Received unexpected 'State' message from the fuzzer. Closing.`;
11896
+ this.sender.close();
11897
+ return;
11898
+ }
11899
+ case MessageType.Error: {
11900
+ handler_logger.log `--> Received unexpected 'Error' message from the fuzzer. Closing.`;
11901
+ this.sender.close();
11902
+ return;
11903
+ }
11904
+ default: {
11905
+ handler_logger.log `--> Received unexpected message type ${JSON.stringify(message)} from the fuzzer. Closing.`;
11906
+ this.sender.close();
11907
+ try {
11908
+ assertNever(message);
11909
+ }
11910
+ catch {
11911
+ return;
11912
+ }
11913
+ }
11914
+ }
11915
+ if (response !== null) {
11916
+ handler_logger.trace `<-- responding with: ${response.type}`;
11917
+ const encoded = Encoder.encodeObject(messageCodec, response, this.spec);
11918
+ this.sender.send(encoded);
11919
+ }
11920
+ else {
11921
+ handler_logger.warn `<-- no response generated for: ${message.type}`;
11922
+ }
11923
+ }
11924
+ onClose({ error }) {
11925
+ handler_logger.log `Closing the v1 handler. Reason: ${error !== undefined ? error.message : "close"}.`;
11926
+ }
11927
+ /** Check if a specific feature is enabled in the session */
11928
+ hasFeature(feature) {
11929
+ return (this.sessionFeatures & feature) !== 0;
11930
+ }
11931
+ }
11932
+
11933
+ ;// CONCATENATED MODULE: ./packages/jam/fuzz-proto/v1/index.ts
11934
+
11935
+
11936
+
11937
+ ;// CONCATENATED MODULE: ./packages/jam/fuzz-proto/index.ts
11938
+
11939
+
11940
+
11943
11941
  ;// CONCATENATED MODULE: ./packages/core/pvm-spi-decoder/memory-conts.ts
11944
11942
  // GP reference: https://graypaper.fluffylabs.dev/#/7e6ff6a/2d32002d3200?v=0.6.7
11945
11943
  const memory_conts_PAGE_SIZE = 2 ** 12; // Z_P from GP
@@ -12192,6 +12190,10 @@ class disputes_DisputesRecords {
12192
12190
  static create({ goodSet, badSet, wonkySet, punishSet }) {
12193
12191
  return new disputes_DisputesRecords(goodSet, badSet, wonkySet, punishSet);
12194
12192
  }
12193
+ goodSetDict;
12194
+ badSetDict;
12195
+ wonkySetDict;
12196
+ punishSetDict;
12195
12197
  constructor(
12196
12198
  /** `goodSet`: all work-reports hashes which were judged to be correct */
12197
12199
  goodSet,
@@ -12205,6 +12207,18 @@ class disputes_DisputesRecords {
12205
12207
  this.badSet = badSet;
12206
12208
  this.wonkySet = wonkySet;
12207
12209
  this.punishSet = punishSet;
12210
+ this.goodSetDict = hash_set_HashSet.from(goodSet.array);
12211
+ this.badSetDict = hash_set_HashSet.from(badSet.array);
12212
+ this.wonkySetDict = hash_set_HashSet.from(wonkySet.array);
12213
+ this.punishSetDict = hash_set_HashSet.from(punishSet.array);
12214
+ }
12215
+ asDictionaries() {
12216
+ return {
12217
+ goodSet: this.goodSetDict,
12218
+ badSet: this.badSetDict,
12219
+ wonkySet: this.wonkySetDict,
12220
+ punishSet: this.punishSetDict,
12221
+ };
12208
12222
  }
12209
12223
  static fromSortedArrays({ goodSet, badSet, wonkySet, punishSet, }) {
12210
12224
  return new disputes_DisputesRecords(sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, goodSet), sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, badSet), sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, wonkySet), sorted_set_SortedSet.fromSortedArray(disputes_hashComparator, punishSet));
@@ -16249,10 +16263,16 @@ function registers_signExtend32To64(value) {
16249
16263
 
16250
16264
  /** Attempt to convert a number into `HostCallIndex`. */
16251
16265
  const host_call_handler_tryAsHostCallIndex = (v) => opaque_asOpaqueType(numbers_tryAsU32(v));
16266
+ /**
16267
+ * Host-call exit reason.
16268
+ *
16269
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/24a30124a501?v=0.7.2
16270
+ */
16252
16271
  var host_call_handler_PvmExecution;
16253
16272
  (function (PvmExecution) {
16254
16273
  PvmExecution[PvmExecution["Halt"] = 0] = "Halt";
16255
16274
  PvmExecution[PvmExecution["Panic"] = 1] = "Panic";
16275
+ PvmExecution[PvmExecution["OOG"] = 2] = "OOG";
16256
16276
  })(host_call_handler_PvmExecution || (host_call_handler_PvmExecution = {}));
16257
16277
  /** A utility function to easily trace a bunch of registers. */
16258
16278
  function host_call_handler_traceRegisters(...regs) {
@@ -17473,6 +17493,17 @@ class page_range_PageRange {
17473
17493
  }
17474
17494
  return new page_range_PageRange(start, length);
17475
17495
  }
17496
+ /** Returns true if the page range is wrapped (`start` >= `end`) and is not empty */
17497
+ isWrapped() {
17498
+ return this.start >= this.end && !this.isEmpty();
17499
+ }
17500
+ /** Checks if given page number is within the range */
17501
+ isInRange(page) {
17502
+ if (this.isWrapped()) {
17503
+ return page >= this.start || page < this.end;
17504
+ }
17505
+ return page >= this.start && page < this.end;
17506
+ }
17476
17507
  /** Checks if a range is empty (`length === 0`) */
17477
17508
  isEmpty() {
17478
17509
  return this.length === 0;
@@ -17852,10 +17883,11 @@ class memory_builder_MemoryBuilder {
17852
17883
  startHeapIndex (${startHeapIndex}) has to be less than or equal to endHeapIndex (${endHeapIndex})
17853
17884
  `;
17854
17885
  this.ensureNotFinalized();
17855
- const range = MemoryRange.fromStartAndLength(startHeapIndex, endHeapIndex - startHeapIndex);
17856
- const pages = PageRange.fromMemoryRange(range);
17857
- for (const pageNumber of pages) {
17858
- if (this.initialMemory.has(pageNumber)) {
17886
+ const heapRange = MemoryRange.fromStartAndLength(startHeapIndex, endHeapIndex - startHeapIndex);
17887
+ const heapPagesRange = PageRange.fromMemoryRange(heapRange);
17888
+ const initializedPageNumbers = Array.from(this.initialMemory.keys());
17889
+ for (const pageNumber of initializedPageNumbers) {
17890
+ if (heapPagesRange.isInRange(pageNumber)) {
17859
17891
  throw new IncorrectSbrkIndex();
17860
17892
  }
17861
17893
  }
@@ -19857,8 +19889,9 @@ class host_calls_HostCalls {
19857
19889
  const index = tryAsHostCallIndex(hostCallIndex);
19858
19890
  const hostCall = this.hostCalls.get(index);
19859
19891
  const gasBefore = gas.get();
19860
- const gasCost = typeof hostCall.gasCost === "number" ? hostCall.gasCost : hostCall.gasCost(regs);
19861
- const underflow = gas.sub(gasCost);
19892
+ // NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
19893
+ const basicGasCost = typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
19894
+ const underflow = gas.sub(basicGasCost);
19862
19895
  const pcLog = `[PC: ${pvmInstance.getPC()}]`;
19863
19896
  if (underflow) {
19864
19897
  this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
@@ -19875,6 +19908,10 @@ class host_calls_HostCalls {
19875
19908
  status = Status.PANIC;
19876
19909
  return this.getReturnValue(status, pvmInstance);
19877
19910
  }
19911
+ if (result === PvmExecution.OOG) {
19912
+ status = Status.OOG;
19913
+ return this.getReturnValue(status, pvmInstance);
19914
+ }
19878
19915
  if (result === undefined) {
19879
19916
  pvmInstance.runProgram();
19880
19917
  status = pvmInstance.getStatus();
@@ -19933,7 +19970,7 @@ class host_calls_manager_HostCallsManager {
19933
19970
  }
19934
19971
  class NoopMissing {
19935
19972
  index = tryAsHostCallIndex(2 ** 32 - 1);
19936
- gasCost = tryAsSmallGas(0);
19973
+ basicGasCost = tryAsSmallGas(0);
19937
19974
  currentServiceId = tryAsU32(0);
19938
19975
  tracedRegisters = [];
19939
19976
  async execute() {
@@ -20047,7 +20084,7 @@ function utils_clampU64ToU32(value) {
20047
20084
 
20048
20085
  class missing_Missing {
20049
20086
  index = tryAsHostCallIndex(2 ** 32 - 1);
20050
- gasCost = tryAsSmallGas(10);
20087
+ basicGasCost = tryAsSmallGas(10);
20051
20088
  currentServiceId = CURRENT_SERVICE_ID;
20052
20089
  tracedRegisters = traceRegisters(7);
20053
20090
  execute(_gas, regs, _memory) {
@@ -20424,7 +20461,7 @@ class disputes_Disputes {
20424
20461
  const { key, workReportHash } = disputes.culprits[i];
20425
20462
  // check if some offenders weren't reported earlier
20426
20463
  // https://graypaper.fluffylabs.dev/#/579bd12/125501125501
20427
- const isInPunishSet = this.state.disputesRecords.punishSet.findExact(key) !== undefined;
20464
+ const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
20428
20465
  if (isInPunishSet) {
20429
20466
  return Result.error(DisputesErrorCode.OffenderAlreadyReported);
20430
20467
  }
@@ -20435,8 +20472,8 @@ class disputes_Disputes {
20435
20472
  }
20436
20473
  // verify if the culprit will be in new bad set
20437
20474
  // https://graypaper.fluffylabs.dev/#/579bd12/124601124601
20438
- const isInNewBadSet = newItems.toAddToBadSet.findExact(workReportHash);
20439
- if (isInNewBadSet === undefined) {
20475
+ const isInNewBadSet = newItems.asDictionaries().badSet.has(workReportHash);
20476
+ if (!isInNewBadSet) {
20440
20477
  return Result.error(DisputesErrorCode.CulpritsVerdictNotBad);
20441
20478
  }
20442
20479
  // verify culprit signature
@@ -20459,7 +20496,7 @@ class disputes_Disputes {
20459
20496
  const { key, workReportHash, wasConsideredValid } = disputes.faults[i];
20460
20497
  // check if some offenders weren't reported earlier
20461
20498
  // https://graypaper.fluffylabs.dev/#/579bd12/12a20112a201
20462
- const isInPunishSet = this.state.disputesRecords.punishSet.findExact(key) !== undefined;
20499
+ const isInPunishSet = this.state.disputesRecords.asDictionaries().punishSet.has(key);
20463
20500
  if (isInPunishSet) {
20464
20501
  return Result.error(DisputesErrorCode.OffenderAlreadyReported);
20465
20502
  }
@@ -20474,9 +20511,10 @@ class disputes_Disputes {
20474
20511
  // but it does not pass the tests
20475
20512
  // https://graypaper.fluffylabs.dev/#/579bd12/128a01129601
20476
20513
  if (wasConsideredValid) {
20477
- const isInNewGoodSet = newItems.toAddToGoodSet.findExact(workReportHash);
20478
- const isInNewBadSet = newItems.toAddToBadSet.findExact(workReportHash);
20479
- if (isInNewGoodSet !== undefined || isInNewBadSet === undefined) {
20514
+ const { goodSet, badSet } = newItems.asDictionaries();
20515
+ const isInNewGoodSet = goodSet.has(workReportHash);
20516
+ const isInNewBadSet = badSet.has(workReportHash);
20517
+ if (isInNewGoodSet || !isInNewBadSet) {
20480
20518
  return Result.error(DisputesErrorCode.FaultVerdictWrong);
20481
20519
  }
20482
20520
  }
@@ -20529,10 +20567,11 @@ class disputes_Disputes {
20529
20567
  for (const verdict of disputes.verdicts) {
20530
20568
  // current verdicts should not be reported earlier
20531
20569
  // https://graypaper.fluffylabs.dev/#/579bd12/122202122202
20532
- const isInGoodSet = this.state.disputesRecords.goodSet.findExact(verdict.workReportHash);
20533
- const isInBadSet = this.state.disputesRecords.badSet.findExact(verdict.workReportHash);
20534
- const isInWonkySet = this.state.disputesRecords.wonkySet.findExact(verdict.workReportHash);
20535
- if (isInGoodSet !== undefined || isInBadSet !== undefined || isInWonkySet !== undefined) {
20570
+ const { goodSet, badSet, wonkySet } = this.state.disputesRecords.asDictionaries();
20571
+ const isInGoodSet = goodSet.has(verdict.workReportHash);
20572
+ const isInBadSet = badSet.has(verdict.workReportHash);
20573
+ const isInWonkySet = wonkySet.has(verdict.workReportHash);
20574
+ if (isInGoodSet || isInBadSet || isInWonkySet) {
20536
20575
  return Result.error(DisputesErrorCode.AlreadyJudged);
20537
20576
  }
20538
20577
  }
@@ -20602,11 +20641,12 @@ class disputes_Disputes {
20602
20641
  toAddToWonkySet.push(r);
20603
20642
  }
20604
20643
  }
20605
- return {
20606
- toAddToGoodSet: SortedSet.fromArrayUnique(hashComparator, toAddToGoodSet),
20607
- toAddToBadSet: SortedSet.fromArrayUnique(hashComparator, toAddToBadSet),
20608
- toAddToWonkySet: SortedSet.fromArrayUnique(hashComparator, toAddToWonkySet),
20609
- };
20644
+ return DisputesRecords.create({
20645
+ goodSet: SortedSet.fromArrayUnique(hashComparator, toAddToGoodSet),
20646
+ badSet: SortedSet.fromArrayUnique(hashComparator, toAddToBadSet),
20647
+ wonkySet: SortedSet.fromArrayUnique(hashComparator, toAddToWonkySet),
20648
+ punishSet: SortedSet.fromArray(hashComparator, []),
20649
+ });
20610
20650
  }
20611
20651
  getClearedCoreAssignment(v) {
20612
20652
  /**
@@ -20641,9 +20681,9 @@ class disputes_Disputes {
20641
20681
  const toAddToPunishSet = SortedArray.fromArray(hashComparator, Array.from(offenders));
20642
20682
  return DisputesRecords.create({
20643
20683
  // https://graypaper.fluffylabs.dev/#/579bd12/12690312bc03
20644
- goodSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.goodSet, newItems.toAddToGoodSet),
20645
- badSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.badSet, newItems.toAddToBadSet),
20646
- wonkySet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.wonkySet, newItems.toAddToWonkySet),
20684
+ goodSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.goodSet, newItems.goodSet),
20685
+ badSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.badSet, newItems.badSet),
20686
+ wonkySet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.wonkySet, newItems.wonkySet),
20647
20687
  punishSet: SortedSet.fromTwoSortedCollections(this.state.disputesRecords.punishSet, toAddToPunishSet),
20648
20688
  });
20649
20689
  }
@@ -23027,7 +23067,7 @@ class Assign {
23027
23067
  partialState;
23028
23068
  chainSpec;
23029
23069
  index = host_call_handler_tryAsHostCallIndex(15);
23030
- gasCost = gas_tryAsSmallGas(10);
23070
+ basicGasCost = gas_tryAsSmallGas(10);
23031
23071
  tracedRegisters = host_call_handler_traceRegisters(IN_OUT_REG, 8);
23032
23072
  constructor(currentServiceId, partialState, chainSpec) {
23033
23073
  this.currentServiceId = currentServiceId;
@@ -23105,7 +23145,7 @@ class Bless {
23105
23145
  partialState;
23106
23146
  chainSpec;
23107
23147
  index = host_call_handler_tryAsHostCallIndex(14);
23108
- gasCost = gas_tryAsSmallGas(10);
23148
+ basicGasCost = gas_tryAsSmallGas(10);
23109
23149
  tracedRegisters = host_call_handler_traceRegisters(bless_IN_OUT_REG, 8, 9, 10, 11);
23110
23150
  constructor(currentServiceId, partialState, chainSpec) {
23111
23151
  this.currentServiceId = currentServiceId;
@@ -23190,7 +23230,7 @@ class Bless {
23190
23230
  class gas_GasHostCall {
23191
23231
  currentServiceId;
23192
23232
  index = host_call_handler_tryAsHostCallIndex(0);
23193
- gasCost = gas_tryAsSmallGas(10);
23233
+ basicGasCost = gas_tryAsSmallGas(10);
23194
23234
  tracedRegisters = host_call_handler_traceRegisters(7);
23195
23235
  constructor(currentServiceId) {
23196
23236
  this.currentServiceId = currentServiceId;
@@ -23217,7 +23257,7 @@ class Checkpoint {
23217
23257
  currentServiceId;
23218
23258
  partialState;
23219
23259
  index = host_call_handler_tryAsHostCallIndex(17);
23220
- gasCost = gas_tryAsSmallGas(10);
23260
+ basicGasCost = gas_tryAsSmallGas(10);
23221
23261
  tracedRegisters;
23222
23262
  gasHostCall;
23223
23263
  constructor(currentServiceId, partialState) {
@@ -23254,7 +23294,7 @@ class Designate {
23254
23294
  partialState;
23255
23295
  chainSpec;
23256
23296
  index = host_call_handler_tryAsHostCallIndex(16);
23257
- gasCost = gas_tryAsSmallGas(10);
23297
+ basicGasCost = gas_tryAsSmallGas(10);
23258
23298
  tracedRegisters = host_call_handler_traceRegisters(designate_IN_OUT_REG);
23259
23299
  constructor(currentServiceId, partialState, chainSpec) {
23260
23300
  this.currentServiceId = currentServiceId;
@@ -23305,7 +23345,7 @@ class Eject {
23305
23345
  currentServiceId;
23306
23346
  partialState;
23307
23347
  index = host_call_handler_tryAsHostCallIndex(21);
23308
- gasCost = gas_tryAsSmallGas(10);
23348
+ basicGasCost = gas_tryAsSmallGas(10);
23309
23349
  tracedRegisters = host_call_handler_traceRegisters(eject_IN_OUT_REG, 8);
23310
23350
  constructor(currentServiceId, partialState) {
23311
23351
  this.currentServiceId = currentServiceId;
@@ -23367,7 +23407,7 @@ class Forget {
23367
23407
  currentServiceId;
23368
23408
  partialState;
23369
23409
  index = host_call_handler_tryAsHostCallIndex(24);
23370
- gasCost = gas_tryAsSmallGas(10);
23410
+ basicGasCost = gas_tryAsSmallGas(10);
23371
23411
  tracedRegisters = host_call_handler_traceRegisters(forget_IN_OUT_REG, 8);
23372
23412
  constructor(currentServiceId, partialState) {
23373
23413
  this.currentServiceId = currentServiceId;
@@ -23417,7 +23457,7 @@ class New {
23417
23457
  currentServiceId;
23418
23458
  partialState;
23419
23459
  index = host_call_handler_tryAsHostCallIndex(18);
23420
- gasCost = gas_tryAsSmallGas(10);
23460
+ basicGasCost = gas_tryAsSmallGas(10);
23421
23461
  tracedRegisters = host_call_handler_traceRegisters(new_IN_OUT_REG, 8, 9, 10, 11);
23422
23462
  constructor(currentServiceId, partialState) {
23423
23463
  this.currentServiceId = currentServiceId;
@@ -23480,7 +23520,7 @@ class Provide {
23480
23520
  currentServiceId;
23481
23521
  partialState;
23482
23522
  index = host_call_handler_tryAsHostCallIndex(26);
23483
- gasCost = gas_tryAsSmallGas(10);
23523
+ basicGasCost = gas_tryAsSmallGas(10);
23484
23524
  tracedRegisters = host_call_handler_traceRegisters(provide_IN_OUT_REG, 8, 9);
23485
23525
  constructor(currentServiceId, partialState) {
23486
23526
  this.currentServiceId = currentServiceId;
@@ -23541,7 +23581,7 @@ class Query {
23541
23581
  currentServiceId;
23542
23582
  partialState;
23543
23583
  index = host_call_handler_tryAsHostCallIndex(22);
23544
- gasCost = gas_tryAsSmallGas(10);
23584
+ basicGasCost = gas_tryAsSmallGas(10);
23545
23585
  tracedRegisters = host_call_handler_traceRegisters(IN_OUT_REG_1, IN_OUT_REG_2);
23546
23586
  constructor(currentServiceId, partialState) {
23547
23587
  this.currentServiceId = currentServiceId;
@@ -23607,7 +23647,7 @@ class Solicit {
23607
23647
  currentServiceId;
23608
23648
  partialState;
23609
23649
  index = host_call_handler_tryAsHostCallIndex(23);
23610
- gasCost = gas_tryAsSmallGas(10);
23650
+ basicGasCost = gas_tryAsSmallGas(10);
23611
23651
  tracedRegisters = host_call_handler_traceRegisters(solicit_IN_OUT_REG, 8);
23612
23652
  constructor(currentServiceId, partialState) {
23613
23653
  this.currentServiceId = currentServiceId;
@@ -23655,12 +23695,12 @@ class Solicit {
23655
23695
 
23656
23696
  const transfer_IN_OUT_REG = 7; // `d`
23657
23697
  const AMOUNT_REG = 8; // `a`
23658
- const ON_TRANSFER_GAS_REG = 9; // `l`
23698
+ const TRANSFER_GAS_FEE_REG = 9; // `l`
23659
23699
  const MEMO_START_REG = 10; // `o`
23660
23700
  /**
23661
23701
  * Transfer balance from one service account to another.
23662
23702
  *
23663
- * https://graypaper.fluffylabs.dev/#/7e6ff6a/373b00373b00?v=0.6.7
23703
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/373f00373f00?v=0.7.2
23664
23704
  */
23665
23705
  class Transfer {
23666
23706
  currentServiceId;
@@ -23672,38 +23712,50 @@ class Transfer {
23672
23712
  },
23673
23713
  }));
23674
23714
  /**
23675
- * `g = 10 + ω9`
23676
- * https://graypaper.fluffylabs.dev/#/7e6ff6a/373d00373d00?v=0.6.7
23715
+ * `g = 10 + t`
23716
+ *
23717
+ * `t` has positive value, only when status of a transfer is `OK`
23718
+ * `0` otherwise
23719
+ *
23720
+ * Pre0.7.2: `g = 10 + ω9`
23721
+ *
23722
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/373f00373f00?v=0.7.2
23677
23723
  */
23678
- gasCost = (regs) => {
23679
- const gas = 10n + regs.get(ON_TRANSFER_GAS_REG);
23680
- return gas_tryAsGas(gas);
23681
- };
23682
- tracedRegisters = host_call_handler_traceRegisters(transfer_IN_OUT_REG, AMOUNT_REG, ON_TRANSFER_GAS_REG, MEMO_START_REG);
23724
+ basicGasCost = compatibility_Compatibility.isGreaterOrEqual(compatibility_GpVersion.V0_7_2)
23725
+ ? gas_tryAsSmallGas(10)
23726
+ : (regs) => gas_tryAsGas(10n + regs.get(TRANSFER_GAS_FEE_REG));
23727
+ tracedRegisters = host_call_handler_traceRegisters(transfer_IN_OUT_REG, AMOUNT_REG, TRANSFER_GAS_FEE_REG, MEMO_START_REG);
23683
23728
  constructor(currentServiceId, partialState) {
23684
23729
  this.currentServiceId = currentServiceId;
23685
23730
  this.partialState = partialState;
23686
23731
  }
23687
- async execute(_gas, regs, memory) {
23732
+ async execute(gas, regs, memory) {
23688
23733
  // `d`: destination
23689
23734
  const destination = getServiceId(regs.get(transfer_IN_OUT_REG));
23690
23735
  // `a`: amount
23691
23736
  const amount = regs.get(AMOUNT_REG);
23692
23737
  // `l`: gas
23693
- const onTransferGas = common_tryAsServiceGas(regs.get(ON_TRANSFER_GAS_REG));
23738
+ const transferGasFee = common_tryAsServiceGas(regs.get(TRANSFER_GAS_FEE_REG));
23694
23739
  // `o`: transfer memo
23695
23740
  const memoStart = regs.get(MEMO_START_REG);
23696
23741
  const memo = bytes_Bytes.zero(TRANSFER_MEMO_BYTES);
23697
23742
  const memoryReadResult = memory.loadInto(memo.raw, memoStart);
23698
23743
  // page fault while reading the memory.
23699
23744
  if (memoryReadResult.isError) {
23700
- logger_logger.trace `TRANSFER(${destination}, ${amount}, ${onTransferGas}, ${memo}) <- PANIC`;
23745
+ logger_logger.trace `TRANSFER(${destination}, ${amount}, ${transferGasFee}, ${memo}) <- PANIC`;
23701
23746
  return host_call_handler_PvmExecution.Panic;
23702
23747
  }
23703
- const transferResult = this.partialState.transfer(destination, amount, onTransferGas, memo);
23704
- logger_logger.trace `TRANSFER(${destination}, ${amount}, ${onTransferGas}, ${memo}) <- ${result_resultToString(transferResult)}`;
23748
+ const transferResult = this.partialState.transfer(destination, amount, transferGasFee, memo);
23749
+ logger_logger.trace `TRANSFER(${destination}, ${amount}, ${transferGasFee}, ${memo}) <- ${result_resultToString(transferResult)}`;
23705
23750
  // All good!
23706
23751
  if (transferResult.isOk) {
23752
+ if (compatibility_Compatibility.isGreaterOrEqual(compatibility_GpVersion.V0_7_2)) {
23753
+ // substracting value `t`
23754
+ const underflow = gas.sub(gas_tryAsGas(transferGasFee));
23755
+ if (underflow) {
23756
+ return host_call_handler_PvmExecution.OOG;
23757
+ }
23758
+ }
23707
23759
  regs.set(transfer_IN_OUT_REG, results_HostCallResult.OK);
23708
23760
  return;
23709
23761
  }
@@ -23743,7 +23795,7 @@ class Upgrade {
23743
23795
  currentServiceId;
23744
23796
  partialState;
23745
23797
  index = host_call_handler_tryAsHostCallIndex(19);
23746
- gasCost = gas_tryAsSmallGas(10);
23798
+ basicGasCost = gas_tryAsSmallGas(10);
23747
23799
  tracedRegisters = host_call_handler_traceRegisters(upgrade_IN_OUT_REG, GAS_REG, ALLOWANCE_REG);
23748
23800
  constructor(currentServiceId, partialState) {
23749
23801
  this.currentServiceId = currentServiceId;
@@ -23786,7 +23838,7 @@ class Yield {
23786
23838
  currentServiceId;
23787
23839
  partialState;
23788
23840
  index = host_call_handler_tryAsHostCallIndex(25);
23789
- gasCost = gas_tryAsSmallGas(10);
23841
+ basicGasCost = gas_tryAsSmallGas(10);
23790
23842
  tracedRegisters = host_call_handler_traceRegisters(yield_IN_OUT_REG);
23791
23843
  constructor(currentServiceId, partialState) {
23792
23844
  this.currentServiceId = currentServiceId;
@@ -23822,7 +23874,7 @@ class fetch_Fetch {
23822
23874
  currentServiceId;
23823
23875
  fetch;
23824
23876
  index = tryAsHostCallIndex(1);
23825
- gasCost = tryAsSmallGas(10);
23877
+ basicGasCost = tryAsSmallGas(10);
23826
23878
  tracedRegisters = traceRegisters(fetch_IN_OUT_REG, 8, 9, 10, 11, 12);
23827
23879
  constructor(currentServiceId, fetch) {
23828
23880
  this.currentServiceId = currentServiceId;
@@ -23979,7 +24031,7 @@ class info_Info {
23979
24031
  currentServiceId;
23980
24032
  account;
23981
24033
  index = tryAsHostCallIndex(5);
23982
- gasCost = tryAsSmallGas(10);
24034
+ basicGasCost = tryAsSmallGas(10);
23983
24035
  tracedRegisters = traceRegisters(info_IN_OUT_REG, 8, OFFSET_REG, LEN_REG);
23984
24036
  constructor(currentServiceId, account) {
23985
24037
  this.currentServiceId = currentServiceId;
@@ -24054,7 +24106,7 @@ const decoder = new TextDecoder("utf8");
24054
24106
  class log_LogHostCall {
24055
24107
  currentServiceId;
24056
24108
  index = tryAsHostCallIndex(100);
24057
- gasCost = tryAsSmallGas(0);
24109
+ basicGasCost = tryAsSmallGas(0);
24058
24110
  // intentionally not tracing anything here, since the message will be printed anyway.
24059
24111
  tracedRegisters = traceRegisters();
24060
24112
  constructor(currentServiceId) {
@@ -24096,7 +24148,7 @@ class lookup_Lookup {
24096
24148
  currentServiceId;
24097
24149
  account;
24098
24150
  index = tryAsHostCallIndex(2);
24099
- gasCost = tryAsSmallGas(10);
24151
+ basicGasCost = tryAsSmallGas(10);
24100
24152
  tracedRegisters = traceRegisters(lookup_IN_OUT_REG, 8, 9, 10, 11);
24101
24153
  constructor(currentServiceId, account) {
24102
24154
  this.currentServiceId = currentServiceId;
@@ -24159,7 +24211,7 @@ class read_Read {
24159
24211
  currentServiceId;
24160
24212
  account;
24161
24213
  index = tryAsHostCallIndex(3);
24162
- gasCost = tryAsSmallGas(10);
24214
+ basicGasCost = tryAsSmallGas(10);
24163
24215
  tracedRegisters = traceRegisters(read_IN_OUT_REG, 8, 9, 10, 11, 12);
24164
24216
  constructor(currentServiceId, account) {
24165
24217
  this.currentServiceId = currentServiceId;
@@ -24229,7 +24281,7 @@ class write_Write {
24229
24281
  currentServiceId;
24230
24282
  account;
24231
24283
  index = tryAsHostCallIndex(4);
24232
- gasCost = tryAsSmallGas(10);
24284
+ basicGasCost = tryAsSmallGas(10);
24233
24285
  tracedRegisters = traceRegisters(write_IN_OUT_REG, 8, 9, 10);
24234
24286
  constructor(currentServiceId, account) {
24235
24287
  this.currentServiceId = currentServiceId;
@@ -26809,6 +26861,12 @@ async function runPvmTest(testContent) {
26809
26861
 
26810
26862
 
26811
26863
 
26864
+ function looseType(output) {
26865
+ return {
26866
+ value: output.value,
26867
+ encode: output.encode,
26868
+ };
26869
+ }
26812
26870
  const SUPPORTED_TYPES = [
26813
26871
  {
26814
26872
  name: "block",
@@ -26826,8 +26884,12 @@ const SUPPORTED_TYPES = [
26826
26884
  run(spec, data, option) {
26827
26885
  const header = data;
26828
26886
  if (option === "as-hash") {
26829
- return hashBytes(encoder_Encoder.encodeObject(header_Header.Codec, header, spec));
26887
+ return looseType({
26888
+ value: hashBytes(encoder_Encoder.encodeObject(header_Header.Codec, header, spec)),
26889
+ encode: descriptors_codec.bytes(hash_HASH_SIZE),
26890
+ });
26830
26891
  }
26892
+ throw new Error(`Invalid processing option: ${option}`);
26831
26893
  },
26832
26894
  },
26833
26895
  },
@@ -26871,11 +26933,17 @@ const SUPPORTED_TYPES = [
26871
26933
  run(spec, data, option) {
26872
26934
  const state = data;
26873
26935
  if (option === "as-entries") {
26874
- return Object.fromEntries(state_entries_StateEntries.serializeInMemory(spec, state));
26936
+ return looseType({
26937
+ value: Object.fromEntries(state_entries_StateEntries.serializeInMemory(spec, state)),
26938
+ });
26875
26939
  }
26876
26940
  if (option === "as-root-hash") {
26877
- return state_entries_StateEntries.serializeInMemory(spec, state).getRootHash();
26941
+ return looseType({
26942
+ value: state_entries_StateEntries.serializeInMemory(spec, state).getRootHash(),
26943
+ encode: descriptors_codec.bytes(hash_HASH_SIZE),
26944
+ });
26878
26945
  }
26946
+ throw new Error(`Invalid processing option: ${option}`);
26879
26947
  },
26880
26948
  },
26881
26949
  },
@@ -26885,19 +26953,39 @@ const SUPPORTED_TYPES = [
26885
26953
  decode: StateTransitionGenesis.Codec,
26886
26954
  json: () => StateTransitionGenesis.fromJson,
26887
26955
  process: {
26888
- options: ["as-state", "as-jip4"],
26956
+ options: ["as-state", "as-jip4", "as-fuzz-message"],
26889
26957
  run(spec, data, option) {
26890
26958
  const test = data;
26891
26959
  if (option === "as-state") {
26892
- return stateFromKeyvals(spec, test.state);
26960
+ return looseType({
26961
+ value: stateFromKeyvals(spec, test.state),
26962
+ });
26893
26963
  }
26894
26964
  if (option === "as-jip4") {
26895
26965
  const genesisState = new Map(test.state.keyvals.map((x) => [x.key, x.value]));
26896
- return JipChainSpec.create({
26897
- genesisHeader: encoder_Encoder.encodeObject(header_Header.Codec, test.header, spec),
26898
- genesisState,
26966
+ return looseType({
26967
+ value: JipChainSpec.create({
26968
+ genesisHeader: encoder_Encoder.encodeObject(header_Header.Codec, test.header, spec),
26969
+ genesisState,
26970
+ }),
26971
+ });
26972
+ }
26973
+ if (option === "as-fuzz-message") {
26974
+ const init = Initialize.create({
26975
+ header: test.header,
26976
+ keyvals: test.state.keyvals,
26977
+ ancestry: [],
26978
+ });
26979
+ const msg = {
26980
+ type: types_MessageType.Initialize,
26981
+ value: init,
26982
+ };
26983
+ return looseType({
26984
+ value: msg,
26985
+ encode: types_messageCodec,
26899
26986
  });
26900
26987
  }
26988
+ throw new Error(`Invalid processing option: ${option}`);
26901
26989
  },
26902
26990
  },
26903
26991
  },
@@ -26907,15 +26995,32 @@ const SUPPORTED_TYPES = [
26907
26995
  decode: StateTransition.Codec,
26908
26996
  json: () => StateTransition.fromJson,
26909
26997
  process: {
26910
- options: ["as-pre-state", "as-post-state"],
26998
+ options: ["as-pre-state", "as-post-state", "as-fuzz-message"],
26911
26999
  run(spec, data, option) {
26912
27000
  const test = data;
26913
27001
  if (option === "as-pre-state") {
26914
- return stateFromKeyvals(spec, test.pre_state);
27002
+ return looseType({
27003
+ value: stateFromKeyvals(spec, test.pre_state),
27004
+ });
26915
27005
  }
26916
27006
  if (option === "as-post-state") {
26917
- return stateFromKeyvals(spec, test.post_state);
27007
+ return looseType({
27008
+ value: stateFromKeyvals(spec, test.post_state),
27009
+ });
27010
+ }
27011
+ if (option === "as-fuzz-message") {
27012
+ const encoded = encoder_Encoder.encodeObject(block_Block.Codec, test.block, spec);
27013
+ const blockView = decoder_Decoder.decodeObject(block_Block.Codec.View, encoded, spec);
27014
+ const msg = {
27015
+ type: types_MessageType.ImportBlock,
27016
+ value: blockView,
27017
+ };
27018
+ return looseType({
27019
+ value: msg,
27020
+ encode: types_messageCodec,
27021
+ });
26918
27022
  }
27023
+ throw new Error(`Invalid processing option: ${option}`);
26919
27024
  },
26920
27025
  },
26921
27026
  },
@@ -26938,7 +27043,7 @@ const HELP = `
26938
27043
  @typeberry/convert ${package_namespaceObject.rE} by Fluffy Labs.
26939
27044
 
26940
27045
  Usage:
26941
- @typeberry/convert [options] <bin-hex-or-json-input-file> <type> [process] [output-format]
27046
+ @typeberry/convert [options] <bin-hex-or-json-input-file> <type> [process] [output-format] [output-file]
26942
27047
 
26943
27048
  Attempts to read provided input file as 'type' and output in requested 'output-format'.
26944
27049
  For some 'type's it's additionally possible to process the data before outputting it.
@@ -26947,6 +27052,7 @@ The input type is detected from file extension ('.bin', '.hex' or '.json').
26947
27052
  Example usage:
26948
27053
  @typeberry/convert ./genesis-header.json header to-hex
26949
27054
  @typeberry/convert ./state-snapshot.json state-dump as-entries to-json
27055
+ @typeberry/convert ./state-snapshot.json stf-vector as-fuzz-message to-bin msg0.bin
26950
27056
 
26951
27057
  Options:
26952
27058
  --flavor - chain spec flavor, either 'full' or 'tiny'.
@@ -26956,6 +27062,7 @@ Output formats:
26956
27062
  to-print - Print the object to the console
26957
27063
  to-json - JSON format (when supported)
26958
27064
  to-hex - JAM-codec hex-encoded string (when supported)
27065
+ to-bin - JAM-codec binary data (when supported)
26959
27066
  to-repl - Start a JavaScript REPL with the data loaded into a variable
26960
27067
 
26961
27068
  Input types:
@@ -26978,6 +27085,7 @@ var OutputFormat;
26978
27085
  OutputFormat["Print"] = "to-print";
26979
27086
  OutputFormat["Json"] = "to-json";
26980
27087
  OutputFormat["Hex"] = "to-hex";
27088
+ OutputFormat["Bin"] = "to-bin";
26981
27089
  OutputFormat["Repl"] = "to-repl";
26982
27090
  })(OutputFormat || (OutputFormat = {}));
26983
27091
  function parseArgs(cliInput, withRelPath) {
@@ -26999,14 +27107,16 @@ function parseArgs(cliInput, withRelPath) {
26999
27107
  const type = parseType(args._.shift());
27000
27108
  const maybeProcess = args._.shift();
27001
27109
  const maybeOutputFormat = args._.shift();
27110
+ const maybeDestination = args._.shift();
27002
27111
  assertNoMoreArgs(args);
27003
- const { process, format } = getProcessAndOutput(type, maybeProcess, maybeOutputFormat);
27112
+ const { process, format, destination } = getProcessFormatAndDestination(type, maybeProcess, maybeOutputFormat, maybeDestination);
27004
27113
  return {
27005
27114
  flavor: chainSpec.flavor,
27006
27115
  type,
27007
27116
  process,
27008
27117
  inputPath: withRelPath(input),
27009
27118
  outputFormat: format,
27119
+ destination,
27010
27120
  };
27011
27121
  }
27012
27122
  function parseType(type) {
@@ -27032,10 +27142,21 @@ function parseOutputFormat(output) {
27032
27142
  return OutputFormat.Json;
27033
27143
  case OutputFormat.Repl:
27034
27144
  return OutputFormat.Repl;
27145
+ case OutputFormat.Bin:
27146
+ return OutputFormat.Bin;
27035
27147
  default:
27036
27148
  throw new Error(`Invalid output format: '${output}'.`);
27037
27149
  }
27038
27150
  }
27151
+ function parseProcess(processOptions, maybeProcess) {
27152
+ if (maybeProcess === undefined) {
27153
+ return null;
27154
+ }
27155
+ if (!processOptions.includes(maybeProcess)) {
27156
+ throw new Error(`Incorrect processing option: ${maybeProcess}. Expected one of: ${processOptions}.`);
27157
+ }
27158
+ return maybeProcess;
27159
+ }
27039
27160
  // TODO [ToDr] Consider sharing that?
27040
27161
  function parseOption(args, option, parser, defaultValue) {
27041
27162
  if (args[option] === undefined) {
@@ -27071,33 +27192,64 @@ function assertNoMoreArgs(args) {
27071
27192
  throw new Error(`Unrecognized options: '${keysLeft}'`);
27072
27193
  }
27073
27194
  }
27074
- function getProcessAndOutput(type, maybeProcess, maybeOutputFormat) {
27195
+ function getProcessFormatAndDestination(type, maybeProcess, maybeOutputFormat, maybeDestination) {
27196
+ const defaultProcess = "";
27075
27197
  const defaultFormat = parseOutputFormat(undefined);
27076
- const options = type.process?.options ?? [];
27077
- // we have both options, so we expect them in the right order.
27078
- if (maybeProcess !== undefined && maybeOutputFormat !== undefined) {
27198
+ const processOptions = type.process?.options ?? [];
27199
+ // we have all three so it must be in order
27200
+ if (maybeProcess !== undefined && maybeOutputFormat !== undefined && maybeDestination !== undefined) {
27079
27201
  const format = parseOutputFormat(maybeOutputFormat);
27080
- if (!options.includes(maybeProcess)) {
27081
- throw new Error(`Incorrect processing option: ${maybeProcess}. Expected one of: ${options}.`);
27082
- }
27083
- return { process: maybeProcess, format };
27202
+ const process = parseProcess(processOptions, maybeProcess) ?? defaultProcess;
27203
+ const destination = maybeDestination;
27204
+ throwIfDumpNotSupported(format, destination);
27205
+ return { process, format, destination };
27206
+ }
27207
+ // we have either:
27208
+ // 1. process + format
27209
+ // 2. format + destination
27210
+ if (maybeProcess !== undefined && maybeOutputFormat !== undefined) {
27211
+ // we've got processing first, so easy-peasy
27212
+ if (processOptions.includes(maybeProcess)) {
27213
+ const format = parseOutputFormat(maybeOutputFormat);
27214
+ throwIfDumpNotSupported(format, null);
27215
+ return { process: maybeProcess, format, destination: null };
27216
+ }
27217
+ // first one has to be format then.
27218
+ const format = parseOutputFormat(maybeProcess);
27219
+ const destination = maybeOutputFormat;
27220
+ throwIfDumpNotSupported(format, destination);
27221
+ return { process: defaultProcess, format, destination };
27084
27222
  }
27085
27223
  // only one parameter, but it can be either output or processing.
27224
+ const destination = null;
27086
27225
  if (maybeProcess !== undefined) {
27087
- if (options.includes(maybeProcess)) {
27088
- return { process: maybeProcess, format: defaultFormat };
27226
+ if (processOptions.includes(maybeProcess)) {
27227
+ return { process: maybeProcess, format: defaultFormat, destination };
27089
27228
  }
27090
27229
  // now it should be output format, but we want to give a better error message,
27091
27230
  // if user mispelled processing.
27092
27231
  try {
27093
27232
  const format = parseOutputFormat(maybeProcess);
27094
- return { process: "", format };
27233
+ throwIfDumpNotSupported(format, destination);
27234
+ return { process: defaultProcess, format, destination };
27095
27235
  }
27096
27236
  catch {
27097
27237
  throw new Error(`'${maybeProcess}' is neither output format nor processing parameter.`);
27098
27238
  }
27099
27239
  }
27100
- return { process: "", format: defaultFormat };
27240
+ return { process: defaultProcess, format: defaultFormat, destination };
27241
+ }
27242
+ function throwIfDumpNotSupported(format, destination) {
27243
+ if (destination !== null) {
27244
+ if (format === OutputFormat.Print || format === OutputFormat.Repl) {
27245
+ throw new Error(`Dumping to file is not supported for ${format}`);
27246
+ }
27247
+ }
27248
+ else {
27249
+ if (format === OutputFormat.Bin) {
27250
+ throw new Error(`${format} requires destination file`);
27251
+ }
27252
+ }
27101
27253
  }
27102
27254
 
27103
27255
  // EXTERNAL MODULE: ./node_modules/json-bigint-patch/dist/index.js
@@ -27157,9 +27309,13 @@ function loadInputFile(file, withRelPath) {
27157
27309
  throw new Error("Input file format unsupported.");
27158
27310
  }
27159
27311
  function dumpOutput(spec, data, type, outputFormat, args, withRelPath) {
27312
+ const { destination } = args;
27313
+ const dump = destination !== null
27314
+ ? (v) => external_node_fs_default().writeFileSync(withRelPath(destination), v)
27315
+ : (v) => console.info(v);
27160
27316
  switch (outputFormat) {
27161
27317
  case OutputFormat.Print: {
27162
- console.info(`${debug_inspect(data)}`);
27318
+ dump(`${debug_inspect(data)}`);
27163
27319
  return;
27164
27320
  }
27165
27321
  case OutputFormat.Hex: {
@@ -27167,13 +27323,24 @@ function dumpOutput(spec, data, type, outputFormat, args, withRelPath) {
27167
27323
  throw new Error(`${type.name} does not support encoding to JAM codec.`);
27168
27324
  }
27169
27325
  const encoded = encoder_Encoder.encodeObject(type.encode, data, spec);
27170
- console.info(`${encoded}`);
27326
+ dump(`${encoded}`);
27327
+ return;
27328
+ }
27329
+ case OutputFormat.Bin: {
27330
+ if (type.encode === undefined) {
27331
+ throw new Error(`${type.name} does not support encoding to JAM codec.`);
27332
+ }
27333
+ if (destination === null) {
27334
+ throw new Error(`${OutputFormat.Bin} requires destination file.`);
27335
+ }
27336
+ const encoded = encoder_Encoder.encodeObject(type.encode, data, spec);
27337
+ dump(encoded.raw);
27171
27338
  return;
27172
27339
  }
27173
27340
  case OutputFormat.Json: {
27174
27341
  // TODO [ToDr] this will probably not work for all cases,
27175
27342
  // but for now may be good enough.
27176
- console.info(toJson(data));
27343
+ dump(toJson(data));
27177
27344
  return;
27178
27345
  }
27179
27346
  case OutputFormat.Repl: {
@@ -27240,6 +27407,9 @@ function toJson(data) {
27240
27407
  if (value instanceof Map) {
27241
27408
  return Object.fromEntries(value.entries());
27242
27409
  }
27410
+ if (value instanceof ObjectView) {
27411
+ return value.materialize();
27412
+ }
27243
27413
  return value;
27244
27414
  }, 2);
27245
27415
  }
@@ -27250,12 +27420,14 @@ function processOutput(spec, data, type, process) {
27250
27420
  if (type.process === undefined || !type.process.options.includes(process)) {
27251
27421
  throw new Error(`Unsupported processing: '${process}' for '${type.name}'`);
27252
27422
  }
27423
+ const processed = type.process.run(spec, data, process);
27253
27424
  return {
27254
- processed: type.process.run(spec, data, process),
27425
+ processed: processed.value,
27255
27426
  type: {
27256
27427
  ...type,
27257
- // disable encoding, since it won't match
27258
- encode: undefined,
27428
+ name: `${type.name}(${process})`,
27429
+ // use encoding from processed type
27430
+ encode: processed.encode,
27259
27431
  },
27260
27432
  };
27261
27433
  }