@acala-network/chopsticks 0.2.0 → 0.2.2

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/README.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Create parallel reality of your Substrate network.
4
4
 
5
+ ## Quick Start
6
+
7
+ Fork Acala mainnet: `yarn dlx @acala-network/chopsticks dev --endpoint=wss://acala-rpc-2.aca-api.network/ws`
8
+
9
+ It is recommended to use config file. You can check [configs](configs/) for examples.
10
+
11
+ You can run a test node with config with `yarn dlx @acala-network/chopsticks dev --config=<config_file_path>`
12
+
5
13
  ## Install
6
14
 
7
15
  Make sure you have setup Rust environment (>= 1.64).
@@ -49,4 +57,3 @@ Make sure you have setup Rust environment (>= 1.64).
49
57
  - Run Kusama fork
50
58
  - Edit configs/kusama.yml if needed. (e.g. update the block number)
51
59
  - `yarn start dev --config=configs/kusama.yml`
52
-
@@ -33,6 +33,7 @@ export declare class Block {
33
33
  get registry(): Promise<TypeRegistry>;
34
34
  get runtimeVersion(): Promise<RuntimeVersion>;
35
35
  get metadata(): Promise<HexString>;
36
+ withAvoidTasks<T>(fn: () => Promise<T>): Promise<T>;
36
37
  get meta(): Promise<DecoratedMeta>;
37
38
  call(method: string, args: string): Promise<TaskResponseCall['Call']>;
38
39
  }
@@ -7,6 +7,7 @@ const util_1 = require("@polkadot/types-known/util");
7
7
  const util_2 = require("@polkadot/util");
8
8
  const storage_layer_1 = require("./storage-layer");
9
9
  const shared_1 = require("../rpc/shared");
10
+ const utils_1 = require("../utils");
10
11
  const executor_1 = require("../executor");
11
12
  class Block {
12
13
  number;
@@ -22,6 +23,7 @@ class Block {
22
23
  #meta;
23
24
  #baseStorage;
24
25
  #storages;
26
+ #avoidTasks = false;
25
27
  constructor(chain, number, hash, parentBlock, block) {
26
28
  this.number = number;
27
29
  this.hash = hash;
@@ -138,10 +140,51 @@ class Block {
138
140
  }
139
141
  get metadata() {
140
142
  if (!this.#metadata) {
141
- this.#metadata = this.wasm.then(executor_1.getMetadata);
143
+ if (this.#avoidTasks) {
144
+ this.#metadata = this.wasm.then(executor_1.getMetadata);
145
+ }
146
+ else {
147
+ this.#metadata = this.wasm.then(async (wasm) => {
148
+ const res = await new Promise((resolve, reject) => {
149
+ this.#chain.tasks.addAndRunTask({
150
+ Call: {
151
+ blockHash: this.hash,
152
+ wasm,
153
+ calls: [['Metadata_metadata', '0x']],
154
+ },
155
+ }, (r) => {
156
+ if ('Call' in r) {
157
+ resolve((0, utils_1.compactHex)((0, util_2.hexToU8a)(r.Call.result)));
158
+ }
159
+ else if ('Error' in r) {
160
+ reject(new shared_1.ResponseError(1, r.Error));
161
+ }
162
+ else {
163
+ reject(new shared_1.ResponseError(1, 'Unexpected response'));
164
+ }
165
+ });
166
+ });
167
+ return res;
168
+ });
169
+ }
142
170
  }
143
171
  return this.#metadata;
144
172
  }
173
+ // TODO: avoid this hack
174
+ // we cannot use this.#chain.tasks during initialization phase
175
+ // but we want to use it after initialization
176
+ async withAvoidTasks(fn) {
177
+ const old = this.#avoidTasks;
178
+ this.#avoidTasks = true;
179
+ try {
180
+ return await fn();
181
+ }
182
+ finally {
183
+ this.#avoidTasks = old;
184
+ this.#meta = undefined;
185
+ this.#metadata = undefined;
186
+ }
187
+ }
145
188
  get meta() {
146
189
  if (!this.#meta) {
147
190
  this.#meta = Promise.all([this.registry, this.metadata]).then(([registry, metadataStr]) => {
@@ -5,19 +5,19 @@ export interface CreateInherents {
5
5
  createInherents(meta: DecoratedMeta, timestamp: number, parent: Block): Promise<string[]>;
6
6
  }
7
7
  export interface InherentProvider extends CreateInherents {
8
- getTimestamp(): number;
8
+ getTimestamp(blockNumber: number): number;
9
9
  }
10
10
  export declare class SetTimestamp implements InherentProvider {
11
11
  #private;
12
- constructor(getTimestamp?: () => number);
12
+ constructor(getTimestamp?: (blockNumber: number) => number);
13
13
  createInherents(meta: DecoratedMeta, timestamp: number, _parent: Block): Promise<string[]>;
14
- getTimestamp(): number;
14
+ getTimestamp(blockNumber: number): number;
15
15
  }
16
16
  export declare class InherentProviders implements InherentProvider {
17
17
  #private;
18
18
  constructor(base: InherentProvider, providers: CreateInherents[]);
19
19
  createInherents(meta: DecoratedMeta, timestamp: number, parent: Block): Promise<string[]>;
20
- getTimestamp(): number;
20
+ getTimestamp(blockNumber: number): number;
21
21
  }
22
22
  export declare class SetValidationData implements CreateInherents {
23
23
  #private;
@@ -2,6 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SetValidationData = exports.InherentProviders = exports.SetTimestamp = void 0;
4
4
  const types_1 = require("@polkadot/types");
5
+ const utils_1 = require("../utils");
6
+ const executor_1 = require("../executor");
7
+ const util_1 = require("@polkadot/util");
8
+ const proof_1 = require("../utils/proof");
5
9
  class SetTimestamp {
6
10
  #getTimestamp;
7
11
  constructor(getTimestamp = Date.now) {
@@ -10,8 +14,8 @@ class SetTimestamp {
10
14
  async createInherents(meta, timestamp, _parent) {
11
15
  return [new types_1.GenericExtrinsic(meta.registry, meta.tx.timestamp.set(timestamp)).toHex()];
12
16
  }
13
- getTimestamp() {
14
- return this.#getTimestamp();
17
+ getTimestamp(blockNumber) {
18
+ return this.#getTimestamp(blockNumber);
15
19
  }
16
20
  }
17
21
  exports.SetTimestamp = SetTimestamp;
@@ -51,8 +55,8 @@ class InherentProviders {
51
55
  const extra = await Promise.all(this.#providers.map((provider) => provider.createInherents(meta, timestamp, parent)));
52
56
  return [...base, ...extra.flat()];
53
57
  }
54
- getTimestamp() {
55
- return this.#base.getTimestamp();
58
+ getTimestamp(blockNumber) {
59
+ return this.#base.getTimestamp(blockNumber);
56
60
  }
57
61
  }
58
62
  exports.InherentProviders = InherentProviders;
@@ -80,12 +84,26 @@ class SetValidationData {
80
84
  }
81
85
  else {
82
86
  const method = meta.registry.createType('GenericExtrinsic', extrinsics[this.#expectedIndex]);
83
- const validationData = method.args[0].toJSON();
87
+ const extrinsic = method.args[0].toJSON();
88
+ const newEntries = [];
89
+ const upgrade = await parentBlock.get((0, utils_1.compactHex)(meta.query.parachainSystem.pendingValidationCode()));
90
+ if (upgrade) {
91
+ const paraIdStorage = await parentBlock.get((0, utils_1.compactHex)(meta.query.parachainInfo.parachainId()));
92
+ const paraId = meta.registry.createType('u32', (0, util_1.hexToU8a)(paraIdStorage));
93
+ const upgradeKey = (0, proof_1.upgradeGoAheadSignal)(paraId);
94
+ const goAhead = meta.registry.createType('UpgradeGoAhead', 'GoAhead');
95
+ newEntries.push([upgradeKey, goAhead.toHex()]);
96
+ }
97
+ const { trieRootHash, nodes } = await (0, executor_1.createProof)(extrinsic.validationData.relayParentStorageRoot, extrinsic.relayChainState.trieNodes, newEntries);
84
98
  newData = {
85
- ...validationData,
99
+ ...extrinsic,
86
100
  validationData: {
87
- ...validationData.validationData,
88
- relayParentNumber: validationData.validationData.relayParentNumber + 2,
101
+ ...extrinsic.validationData,
102
+ relayParentStorageRoot: trieRootHash,
103
+ relayParentNumber: extrinsic.validationData.relayParentNumber + 2,
104
+ },
105
+ relayChainState: {
106
+ trieNodes: nodes,
89
107
  },
90
108
  };
91
109
  }
@@ -62,7 +62,7 @@ class TxPool {
62
62
  const extrinsics = this.#pool.splice(0);
63
63
  const meta = await head.meta;
64
64
  const parentHeader = await head.header;
65
- const time = this.#inherentProvider.getTimestamp();
65
+ const time = this.#inherentProvider.getTimestamp(head.number + 1);
66
66
  let newLogs = parentHeader.digest.logs;
67
67
  const expectedSlot = Math.floor(time / (meta.consts.timestamp.minimumPeriod.toNumber() * 2));
68
68
  const consensus = getConsensus(parentHeader);
@@ -72,7 +72,7 @@ class TxPool {
72
72
  }
73
73
  else if (consensus?.consensusEngine.isBabe) {
74
74
  // trying to make a SecondaryPlainPreDigest
75
- const newSlot = (0, util_1.compactAddLength)((0, util_1.u8aConcat)('0x02000000', (0, util_1.bnToU8a)(expectedSlot, { isLe: true, bitLength: 64 })));
75
+ const newSlot = (0, util_1.compactAddLength)((0, util_1.u8aConcat)('0x0200000000', (0, util_1.bnToU8a)(expectedSlot, { isLe: true, bitLength: 64 })));
76
76
  newLogs = [{ PreRuntime: [consensus.consensusEngine, newSlot] }, ...consensus.rest];
77
77
  }
78
78
  const registry = await head.registry;
@@ -91,6 +91,8 @@ class TxPool {
91
91
  number: head.number,
92
92
  extrinsicsCount: extrinsics.length,
93
93
  tempHash: newBlock.hash,
94
+ timeValue: time,
95
+ expectedSlot,
94
96
  }, 'Building block');
95
97
  const resp = await newBlock.call('Core_initialize_block', header.toHex());
96
98
  logger.trace(resp.storageDiff, 'Initialize block');
@@ -113,17 +115,6 @@ class TxPool {
113
115
  throw new shared_1.ResponseError(1, 'Failed to apply inherents');
114
116
  }
115
117
  }
116
- if (meta.query.parachainSystem?.validationData) {
117
- // this is a parachain
118
- const validationDataKey = (0, utils_1.compactHex)(meta.query.parachainSystem.validationData());
119
- const validationData = await newBlock.get(validationDataKey);
120
- if (!validationData) {
121
- // there is no set validation data inherent
122
- // so we need to restore the old validation data to make the on_finalize check happy
123
- const oldValidationData = await head.get(validationDataKey);
124
- newBlock.pushStorageLayer().set(validationDataKey, oldValidationData);
125
- }
126
- }
127
118
  for (const extrinsic of extrinsics) {
128
119
  try {
129
120
  const resp = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
@@ -1,5 +1,5 @@
1
1
  import { HexString } from '@polkadot/util/types';
2
- import { run_task } from '@acala-network/chopsticks-executor';
2
+ import { run_task } from '../executor/pkg';
3
3
  export type RuntimeVersion = {
4
4
  specName: string;
5
5
  implName: string;
@@ -13,4 +13,9 @@ export type RuntimeVersion = {
13
13
  export declare const getRuntimeVersion: (code: HexString) => Promise<RuntimeVersion>;
14
14
  export declare const getMetadata: (code: HexString) => Promise<HexString>;
15
15
  export declare const calculateStateRoot: (entries: [HexString, HexString][]) => Promise<HexString>;
16
+ export declare const decodeProof: (trieRootHash: HexString, keys: HexString[], nodes: HexString[]) => Promise<Record<`0x${string}`, `0x${string}` | null>>;
17
+ export declare const createProof: (trieRootHash: HexString, nodes: HexString[], entries: [HexString, HexString][]) => Promise<{
18
+ trieRootHash: `0x${string}`;
19
+ nodes: `0x${string}`[];
20
+ }>;
16
21
  export { run_task as runTask };
package/dist/executor.js CHANGED
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runTask = exports.calculateStateRoot = exports.getMetadata = exports.getRuntimeVersion = void 0;
3
+ exports.runTask = exports.createProof = exports.decodeProof = exports.calculateStateRoot = exports.getMetadata = exports.getRuntimeVersion = void 0;
4
4
  const ws_1 = require("ws");
5
5
  const util_1 = require("@polkadot/util");
6
6
  global.WebSocket = ws_1.WebSocket;
7
- const chopsticks_executor_1 = require("@acala-network/chopsticks-executor");
8
- Object.defineProperty(exports, "runTask", { enumerable: true, get: function () { return chopsticks_executor_1.run_task; } });
7
+ const pkg_1 = require("../executor/pkg");
8
+ Object.defineProperty(exports, "runTask", { enumerable: true, get: function () { return pkg_1.run_task; } });
9
9
  const utils_1 = require("./utils");
10
10
  const getRuntimeVersion = async (code) => {
11
- return (0, chopsticks_executor_1.get_runtime_version)(code).then((version) => {
11
+ return (0, pkg_1.get_runtime_version)(code).then((version) => {
12
12
  version.specName = (0, util_1.hexToString)(version.specName);
13
13
  version.implName = (0, util_1.hexToString)(version.implName);
14
14
  return version;
@@ -16,10 +16,27 @@ const getRuntimeVersion = async (code) => {
16
16
  };
17
17
  exports.getRuntimeVersion = getRuntimeVersion;
18
18
  const getMetadata = async (code) => {
19
- return (0, utils_1.compactHex)((0, util_1.hexToU8a)(await (0, chopsticks_executor_1.get_metadata)(code)));
19
+ return (0, utils_1.compactHex)((0, util_1.hexToU8a)(await (0, pkg_1.get_metadata)(code)));
20
20
  };
21
21
  exports.getMetadata = getMetadata;
22
22
  const calculateStateRoot = async (entries) => {
23
- return (0, chopsticks_executor_1.calculate_state_root)(entries);
23
+ return (0, pkg_1.calculate_state_root)(entries);
24
24
  };
25
25
  exports.calculateStateRoot = calculateStateRoot;
26
+ const nodesAddLength = (nodes) => {
27
+ const nodesWithLength = nodes.map((x) => (0, util_1.compactAddLength)((0, util_1.hexToU8a)(x)));
28
+ return (0, util_1.u8aToHex)((0, util_1.u8aConcatStrict)([(0, util_1.compactToU8a)(nodesWithLength.length), (0, util_1.u8aConcat)(...nodesWithLength)]));
29
+ };
30
+ const decodeProof = async (trieRootHash, keys, nodes) => {
31
+ const decoded = await (0, pkg_1.decode_proof)(trieRootHash, keys, nodesAddLength(nodes));
32
+ return decoded.reduce((accum, [key, value]) => {
33
+ accum[key] = value;
34
+ return accum;
35
+ }, {});
36
+ };
37
+ exports.decodeProof = decodeProof;
38
+ const createProof = async (trieRootHash, nodes, entries) => {
39
+ const result = await (0, pkg_1.create_proof)(trieRootHash, nodesAddLength(nodes), entries);
40
+ return { trieRootHash: result[0], nodes: result[1] };
41
+ };
42
+ exports.createProof = createProof;
@@ -5,11 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const metadata_1 = require("@polkadot/types/metadata");
7
7
  const types_1 = require("@polkadot/types");
8
- const executor_1 = require("./executor");
9
8
  const decorate_1 = require("@polkadot/types/metadata/decorate");
10
9
  const vitest_1 = require("vitest");
11
10
  const node_fs_1 = require("node:fs");
12
11
  const node_path_1 = __importDefault(require("node:path"));
12
+ const proof_1 = require("./utils/proof");
13
+ const executor_1 = require("./executor");
13
14
  (0, vitest_1.describe)('wasm', () => {
14
15
  (0, vitest_1.it)('get metadata from wasm runtime', async () => {
15
16
  const code = String((0, node_fs_1.readFileSync)(node_path_1.default.join(__dirname, 'runtime.example'))).trim();
@@ -55,4 +56,88 @@ const node_path_1 = __importDefault(require("node:path"));
55
56
  const b = await (0, executor_1.calculateStateRoot)([['0x5301bf5ff0298f5c7b93a446709f8e885f772afdd0d8ba3d4d559a06f0742f12', '0x02']]);
56
57
  (0, vitest_1.expect)(a).to.not.eq(b);
57
58
  });
59
+ (0, vitest_1.it)('decode & create proof works', async () => {
60
+ // from acala chain
61
+ const ROOT_TRIE_HASH = '0x4a8902b29241020b24b4a1620d0154f756b81ffbcf739a9f06d3447df8123ebd';
62
+ const NODES = [
63
+ '0x5703f5a4efb16ffa83d007000080d205bfd64a59c64fe84480fda7dafd773cb029530c4efe8441bf1f4332bfa48a',
64
+ '0x5703f5a4efb16ffa83d00700008420e8030000d4070000d6070000db070000dc070000f0070000f2070000f3070000',
65
+ '0x5c8c2de8299067f3070000d0070000d4e8030000009001000090010000000000000000000000e8764817000000000000000000000000e87648170000000000000000000000',
66
+ '0x5d0452a22bee61fad0070000f20700005501e80300000090010000900100000000000000000001e41d29d36ff0b7c6007ec17b68ba6165066170fc67eb9755fbd7ed60bef647c100e8764817000000000000000000000000e87648170000000000000000000000',
67
+ '0x5d04d2a15ab51127e8030000d0070000d4e8030000009001000090010000000000000000000000e8764817000000000000000000000000e87648170000000000000000000000',
68
+ '0x5d07edc4cbc65e03d0070000d40700005501e80300000090010000900100000000000000000001708391b220ce64bab1cc4f79559352e59882ee5bb58329085c2400079c56153a00e8764817000000000000000000000000e87648170000000000000000000000',
69
+ '0x5d0b652b2ae6ed1ddc070000d00700005501e803000000900100009001000000000000000000010a492e67d36615052a89ba50498ed5cf0a587b31fd6f3da464e5d111e4e8a81c00e8764817000000000000000000000000e87648170000000000000000000000',
70
+ '0x5d0be1ee506d55f8d0070000f3070000d4e8030000009001000090010000000000000000000000e8764817000000000000000000000000e87648170000000000000000000000',
71
+ '0x5d0c472775baca93f0070000d00700005501e803000000900100009001000000000000000000013b264b3f72ecfeddbdad3b409887206a18d387f1b81856c0383014c9f559992000e8764817000000000000000000000000e87648170000000000000000000000',
72
+ '0x5e046fae65527199f2070000d0070000d4e8030000009001000090010000000000000000000000e8764817000000000000000000000000e87648170000000000000000000000',
73
+ '0x5e057a605f506cfcd4070000d00700005501e80300000090010000900100000000000000000001d3772d60305c2cbd7acf502a11881e0eef47fdfc85c7d2a0d6241e06ea4a971000e8764817000000000000000000000000e87648170000000000000000000000',
74
+ '0x5e36ad4314650419d0070000f00700005501e80300000090010000900100000000000000000001de18e43e692ffe15ea7a85abbce774e6944c56270a846777352827c7596f6c3e00e8764817000000000000000000000000e87648170000000000000000000000',
75
+ '0x5e36c65ca123d5fbd0070000dc0700005501e80300000090010000900100000000000000000001c5120071fe1663a5a21b96d87446ac903ef1bf87dd729b8b9e92ca42ca303e7400e8764817000000000000000000000000e87648170000000000000000000000',
76
+ '0x5e414cb008e0e61e46722aa60abdd67280b46e626e564d1385d21257d8cb59236ca125657f2a14bebd1af174317ca1055c',
77
+ '0x5e4361975d97255ddb070000d00700005501e803000000900100009001000000000000000000018c74408c28f6627f58a8e10b3ec06b98b0166bfb148641a35c5cdfc7a56e68fb00e8764817000000000000000000000000e87648170000000000000000000000',
78
+ '0x5e4f36708366b722d0070000e8030000d4e8030000009001000090010000000000000000000000e8764817000000000000000000000000e87648170000000000000000000000',
79
+ '0x5e55c8e02d73966fd6070000d00700005501e803000000900100009001000000000000000000019a436c9ae233f8b3cc6a379dc35ff6a3c4153b22a96db9fc81c9cee506a252b900e8764817000000000000000000000000e87648170000000000000000000000',
80
+ '0x5e77dfdb8adb10f78f10a5df8742c545840159a565b0fb89d8eec07b522e4e30e8bc29489ef7a9609dfec01855bd125d2e33',
81
+ '0x5ea99274c2ff3639d0070000d60700005501e80300000090010000900100000000000000000001d10c375b7f3756dd38a6fd0967fa4a92199606619c76c5aedc139eb584e8628b00e8764817000000000000000000000000e87648170000000000000000000000',
82
+ '0x5ec648b30353eed1d0070000db0700005501e8030000009001000090010000000000000000000100382d804f7b02c95c2d6b3b6a9cad2c97c2d7570bdfd32f8e8d961754b74b6d00e8764817000000000000000000000000e87648170000000000000000000000',
83
+ '0x5ee678799d3eff024253b90e84927cc68013c6d5340826d75f6258aad1cf4478c20cae5bbaf189e2fe6e0c997aec0a8c3c',
84
+ '0x5f04b49d95320d9021994c850f25b8e3852d030000a000005000000a00000000c8000000c800000a0000000a00000040380000580200000000500000c8000000e87648170000001e0000000000000000e8764817000000000000000000000000e87648170000000000000000000000e8030000009001001e00000000000000009001004038000000000000000000000a0000000a0000000a00000001000000010500000001c8000000060000005802000002000000580200000200000059000000000000001e0000002800000000c817a804000000000200000014000000',
85
+ '0x800014808fc31cedc9f5a694fdde1823788928749f52e1c637dfbf315637fd89eace451c80b58f7e709e14c8ad32651a7b6f13b2ee8aa4a9566413b985e64eb5f3918a58e9',
86
+ '0x800102802dcdd284f422a6ebda6a6f25c88e3ffe11d1adba81950ba92c640b042c250b1080c3883d3173954c1f95c3cb0612d3445f79eaf866255c3261671c3d50a480dcca',
87
+ '0x80011080453fad35c0a01e1a2af068a21c24622fe089db8330ff1c3d52d3a00c7504e515800ebe650369ce0e3ce85b22816181f598cc6ecf7a3b22314357ab4181b9ccb867',
88
+ '0x80011080bfead2545bbb18bbeccbbc42e419ce81be803a019bc10bc035e040209109ca708029f01a3bcd0dedb0dd8e6953b1c52deb161fb6f06b943a1934bd80506ac8f8ff',
89
+ '0x80046480f2126bccffb3e85172709b56414860c2d5aef6fbdca97efb91b0c7989b2e767c809bbc710130cd3fd1008762577f5a4f1959819fefe31aa2eb38c950b5b0ac16748022cba5584bc0982277b50978b65dd7c8c3702937804ae5b16b7b2dbae18122ff80c2e805afdfad80977cb420fe3c56c481131d8e6575e9dac18bfb48ee70bc5a93',
90
+ '0x80080480b64e0437daeee2d16022caa8e4cb67d9bfff7c5feb34dbbe044da77783421f78809ffe6dc440b4ca64053f01647b2e2d3284a4be15517f6693ee26fe4a84cc8a7b',
91
+ '0x8008208057bb9d54329c52084dafd34bb7a12ae243ed81b29438b7941ad6b08bc0aab080485ead6eef5c4b1c68eaa71ea17a02d9de0400',
92
+ '0x8008c280666c2b4c33ef871664a1cd5f75688bd687415a95f52a12fdaff5e1bb1d714f958049da90db410ddc5fcb63a6ba31fff1140f1f027eab9f575207946938a6dff0498032b1eb1b88050e8be5253bc631c21e5bb73b440ae1188f1da9e141aea5050345800892f12109affae95d1fa83c3e98639ce4aa22b3317846989ac8cc46a37ff2bf',
93
+ '0x801017800bd4a887368b253b446f6743e0b8b47e3384a11be255c56869ac5c22c8989dd8800bce23fe3d2d5b8d0e3a26b96ca234ad713326991a44cb1f30acd20cb8eb400080b47bdf3c44e033a0f6273db0e4d3c805462f92c8ec58046e6ece49d93264edaf80ea85a25e4978d8d9281242dec4943257cfb4d14f3408640b5e643f247d38a91c808a15b3c07f5df5f0771146cf6adb06d2d2af1c9c569c70e42d3d881e60c49cb8',
94
+ '0x801040809d953a8e74f031a6e10d7532012f6e655a37c85c4e37454174b98a7b92ced3f9805f738e2d7016159bb83f0acfc05b94f3bfed39826328fbea9a5a6844b0ee9f62',
95
+ '0x801200802c2bdbfc1bde7cdde01a4db7315c02e0373e1c8b826258e135ded3ca12b9b0e580a18673b451b154098a7a400495526a375c86a62e3c8f6def0a67b00eb6d26e87',
96
+ '0x80132680db8ba95d9fa6771a636c09a99827a9ef71777f6507eb4f789de5e137a7250d3780d99bcdfbfe4d2ba16f4dfaa93a02a3853cbc7912bad01d8f89acd4a18e318e9d807e84d35633382d5c74d5c446d26db1cc01db605ba0c12d399849032872bb731280ac082de8a8e688e9aa6c8d9f06576be0b982e6f7229e7b1f3a0d0cbff4e9cbce80e8f2d389ed545a028c6321d265c650179ed1c671fcfbc417185682c21667059b80a512dfa55fcf04f7e26b5ccdc14466086df66928a4f54dfb12b9873108dbfe88',
97
+ '0x8028388028462a6785718dce363f9fa86db6e6885c1df439739c06df2670b71ca7d1d6ab80f12b3be1de5704b86affeaf4178a0ca8dea056893c12a03c3500ca8af78c128080ae634ca22841dbcd3de33dfcd0730d87335dc93786dec63ff9ff5c494b1c32d2802166c372b218427bae449c6e50a075b4bc604253cea4ad0ee8ee7c16b498f3e9808b81a047e908564423ad8d63ef1677199bb5d41570df5ce359ec0cdc5a66fc06',
98
+ '0x80324680aa309aa88e45c23a7b3361cb9ac5bde5896dde657e8a562ce46cd5587674824080f7f61a745a9fefb91f35658a78ebc397ad0514232c0eec10344331b9a29195b680480c6b47252c3414177fcd8441cc689703241343e1ef84be0b206cc24b043f1c80608329e88f9837bedc55fa039c1c5468fe76304edacab49f89a35685ce0492748043a4144332df717cb9ac20b2b490345f22543965ea5272ce3511fa98f4ddfdcb80c62f5d20c25775fb8a8abded53ae1f6abd8fb9f9d75e306a1973194a9a739f73',
99
+ '0x804008804c9c79007d5b06217f77869639dbf475761b1d45115441ea15641d7db01d2425808c68f773671aec1db46b2c37b4c827e64aa7290d65e305cdaaa6b175596256f1',
100
+ '0x8041088041558830b346eebf7648fb84310d961de185de6ebc1bd22d114980d7793d6ee1804e23dcce96d9e514271688cf0bc5581e5e6e74cc4e079c39e75490ac45272f668071daa4762bcd3732d275bee68e3bb098a140029d7b01e82b4cd106924313f9f6',
101
+ '0x80505480a1fc2c779380c33b94b304c281e55ca5a0807804fe9530c22fdfa76628beb42680a1a8a2d4670241007470d59433dc876b10443654c68ee2c22e43f0505fb7081380cbc649bccb6cbe2678b258eb56b9985865852f8dc3ca4ac4608b46dc9a61a56580379357c2c5523ead8e26c2bd4d0ce06ca7f1726b09ef513a7d501aaa5752368280692755c9209155bd724071de137657f492de5bb5479738d1af7119739b4df473',
102
+ '0x80650080021eceb7212a84c0ce28538807a932d56f7ca04ad18a37eb5a3d81cf2d3a1e888028c2012c52668080a70a29a2704a0e1d108658aa94f21e0dcd5103401c52fff3809264b71d425330b4faf06bc3855662ae7511e854ed5387b3ee8c3fafcd6772d080af579d5ddc5c697d42bfc014076594e66c7b324cfd3017810c4e93e4f6f0ae9e',
103
+ '0x8080018068269bb8490669b94a5f1e0c3b4864e03224a2048271f11b8a95ea6168756573805dc031eeca4040dfb7be6e148287360e67d5ce62125f23d912e7ba6b5e1c3ea8',
104
+ '0x8086108046ea793674e4b7c40067c83aa00ac2fbbf3d2ebd57e01d5065909769da0ea9a2801eacd1970b27e7428c46fc7a1cd539390d664880f8665d1f5d9df711aef78ffc807b7ad6eb73914fd07fc55ad89ba771070c1da532a9269475dc64f1995d4d92668044a0d27ae2362402e5ac6666cbfd7bcaa530f2ea97a73b328a13ece4264ea290',
105
+ '0x80a06b8001abdee51ff39c1b87147abb00a81ce05a7b7bbd43dc1509cb4d97acdf3f8e6d80a296acd1c3810d5724e101343410a44934ed827a0c6931e538c2fc095adac046806661dfd17874a64f7f8e2a1e88db6fe81031f845e8705d6470bd48bef2d9615080df3c444cc602cfb8e35514a12c70fe2f5b2ec2683a3e19889c2bce42e8df423180decf6a9a942e385c520acce9b20917c7a516fee686baab2ca15379828a54ec09808cc9995c94f73aec7861dcd2bb4e389eefad87f4d8c1ece831dbcae8c85f2ab4808bbdb281c19f2e0405ebdcdd3eed583c83be8c5bf317070ab8e144c77aecab54',
106
+ '0x80a090809d70976e45bed6bfbe01cc3a2d2fc8d707784be7b54c5910eda9d60dbaa8dcda80c7d17ef601008c6b5fb577a67c8c0ed8f8a1b4eea0109830cddfc3d05c5955b8808fac6f5b26a0a091512ba579c768e78cd75b5f91ff02dcd27a011a1b9d3f8ca0805fc8b08bf7e5d96506fca5e15f58b00e5857510be132ddf21222fdc441242af5',
107
+ '0x80ffff80c66d277de66aaf06e0d6a1fc26ce21d8f6ef50ff28e14dbccfb2fa5bfbd0e5d680f219622acbd014476d4edb56ff6b86554c683a93a217b9ee5449d5f97350aba980daacb402b9d9534826030a1a087c3a6064f823d9578216b50dcc839b4a1cb4f080538c5f0315259d01b9589faf05886e3222ad437f11afbc79f8ca8fd1a706948b803b47dc6cc57a291d93e562eb748a4f6d5ba08cbd1b4b9980117eceff1ce541f08080b4dd653d14508ffe4e711984c6daebb8c53ffc701bc6c390f170524fe6067e806881eae5c901b2f9da23fc14a7b5c5adddf42803d9e6f6457502263d5c20d1b180552af8589e75bd85f77e14ad29a64b58bf27795087e0f8405f00e0af8c44769180f778234884d04539ae5ee94481786900f08bec239bc9e8a495e44f56ae62bd6f8058c056dc712c11a8aacceb99692e0b12b11fa7d127c512373d6a9312e4b7aa12800b7d692bbe193862e80155a0c60d515e359fc0711797aa73b963f8de206372318032b4da4f9707c28268fda915bad17740b2f29044af3426b93dddb1525d9119a180712826eb964d50810e03c64f0465e9d0aefba0975922e3546c1dd289ae6485ab803fc6afb3bb1a772c1b7865d617175918a1e561e7f9f6d4b3727e2e77d8cd54fd80b84b7a6e9b8ac582dfe53a66e6da54a2bc42162390b409a4fb1cb4d99e823334805ab928b4a3b5103f34f6d934e7c2a71a08f6160242d5a25e8d395f022137b544',
108
+ '0x8109400180c7192966ab02c8fe706a869d280b1f9e4100cd344a11d14d330d2691c06d838080cc5ba161e4197291e156c96df507a376d778fdd94adb9db8cc0f457222957ed9',
109
+ '0x810f080880d066a00dc79b0a8601ea466d09a4c969c246ed7d8b4f029afcd41944e33ae8b08063fee100c551b8c3283651ee6d6aad37bbe2abd5830b3c17785b691c63857dc5',
110
+ '0x9d0da05ca59913bc38a8630590f2627c07d980d131600ec39249fb7e25ce8b2759cbe5d9d22d65865cbdc5d5b6b43442a037a28064d55117d3f84fb235f2051b42475f6a3c165cb066016a54582116560d278c0180868f6dfc79ccadf3a96cf90a2b80fcc7fe47c77e30cbb2c8b88a6f3ee21a7c0a8039ebc92b31a26e4935b2e3ac747dfd531b73be08467c9918cc70090e0ae8859b80090170c9487096f84239151a9ecf92c1efeece708d87844f19f56988ec479a0d80a83b5e3737bfc99ede5e597406cf5b001b7949a5315953134fc321fc8992c0bd80fe20d9a744142b01474930a28d8b9a5ef3c851504a99fed5a4fec46d0533c7d88015dd6cf6cccb6c66a9e56feb41c47cf30a31d39fa77ec8b2eb55dd742db53921',
111
+ '0x9e207f03cfdce586301014700e2c2593414080776fdf331ededb557c273c87efa8d2e3919d6745e8645214665bf43afed8b5e9685f0d9ef3b78afddab7f5c7142131132ad42001000000000000004c5f0ec2d17a76153ff51817f12d9cfc3c7f0400',
112
+ '0x9e710b30bd2eab0352ddcc26417aa1944fc380926c6b63b2fdc00d98403a06793b323674ed75b32e75389a2c9d19140f48d07b80db9c2d25d50f7d4f8c69ee037a096b488bc42e33d2cfeeeff1fe8fc22c8cc1788034979b2e5ea91011d05f74f35d25c5b0da29c03c2c0e8e6b9f0a49ca32f46e58800e21335793e29a09c8eac52a4ed197378fd1ac3552ff31aecddb063d3f2c2f314c5f03c716fb8fff3de61a883bb76adb34a20400803587aeceb149eff2f59b5270a01e8c4fd19d1722eab53bcd8b5fd2aee0606fc14c5f0f4993f016e2d2f8e5f43be7bb2594860400807d9800e301836dcc17032891ceff52fc4029dcef8fc74a471e164eb06eecadaf80ac20693eb2298f6f300752834c3fc31a3c075a4e9a77a67d7ee3d6982d70e3e1',
113
+ '0x9eb6f36e027abb2091cfb5110ab5087ff96e685f06155b3cd9a8c9e5e9a23fd5dc13a5ed20873c991000000000685f08316cbf8fa0da822a20ac1c55bf1be320cc15000000000000505f0e7b9012096b41c4eb3aaf947f6ea429080000805788707c580bffc1660dc8c31ca562b5adf72d7dda390c9016319224cedab6c08084a80a22d77d8016adc89610b528c15ba17e4522a53faec0e60d84f5130362a580950cc9876d11a25f6c56e833f048b7fc32caf0bfbb8d9ff4b6ea993f4e984698800d49fef039517cc312c00412803ca1df50ac6d90c50541f649a9c85b83c0fdd8807a5d73d6c6a648545a7a8de535f9a12c2f7105d012e0eb272d91fb8ec018a2bf80cc59c8e5010713cf8876c314769c49fbe0b9a6e131ebf5a9774f52fe73d9ac66800c999e682e20f4c5ab236641829330b52e9a60e3bb8295c671ae10b0078b1b39685f090e2fbf2d792cb324bffa9427fe1f0e20b94ccb00fa55cb00',
114
+ '0x9ede3d8a54d27e44a9d5ce189618f22d3008505f0e7b9012096b41c4eb3aaf947f6ea4290802004c5f03b4123b2e186e07fb7bad5dda5f55c00400806b5403551f8463a3ddf5063c0454a5bd46c9c3d2e1030a6a838a27cc0c4b983a',
115
+ '0x9ef78c98723ddc9073523ef3beefda0c1004809efa6d0e486c88a89d0cec81b8d06f9b5b1dcff9db2c44a9bca135e300ee700c80a8a03c435efb3b22807974e7d4ef1ebad070a3e9c608ed0e5112c1d7223ca5ea',
116
+ '0x9f012b746dcf32e843354583c9702cc020cabb80ff9bed925038b8804f63090b1e2cf36d0d987e2e85b24f046ceee2d849dd69ff80d11d71ea91a8cbe9858770d23355ed19ad19a263b94d55f6d6f503c17eb3dd5280bb7fd6b2fa22db69bca4f70304addc539798fc6174ddae0c5865c71ff96e53415c5700bd9a93e85e3ce1d20700002408d6070000dc07000080b67cef76f1fdf97b48c1fcba9594f1ae40742c195b8d950ae7f08e4b3314fb2780fd53aee7d7ccb0767af55024401273b0a9437c5917cdd60d406dac4aab722333801bff773d6d6d765292b4e595ee0cd425bebe341c2f21af1768896cbfb71cc5d04c57077a93d174890f1ff20700001404d0070000806e5feeb98858d49ab4f600b9337280df82041595257c4d566175cbf59cc105f680f44d2eba0587ca4f414fe092f163abb43531c554c28cfcc26cf032083a7af9b4',
117
+ '0x9f06604cff828a6e3f579ca6c59ace013df7ff801afb0ed9ee8eab53f55af9e9f1c49736c6186c5852d7bba27baeab053a2d22fc809c793f0292c00ae878a17876cc7fe3343623734664aeb50333eac67dd4077b40808aaa7d061d20c8b96edc45a36746cfc2f8645b20db12f51ca020ed4967049c20804c9d12d0f9b7ab988d1ed94f3972945784bf8fb75767e41b3dc5f12410377c5c8048ddad220fd43771ed93688597e2e167308755101c343e6d465739e1f748a699806ae40eb731b53990d314bc9635edeb0f4f45870cf3d6db37bf48d2343547d2cf8005198aaee0fd5761c623207eea8ad53f057e9de0446cd00c23da5ff1c8183ec7809621a90e7fa3e8ed459a6e474ef84a300363f0d245d36a0851a191240462d6e680e2d358899753b8e0b96e95191efba0fba2333c8e526737b6976fa7b413cfa3b980f42207a985ccdcd35ae1ff027a2611b93edb846fe723806a980b082e6328715f809e314bdc1d2c60c13fd046b06bc81c65bcaad55d821e83a9c2dc31293e5ae21780f08e4a062dfbb903d956382db84eadd0bf0a7b2b8468d8cfed83802de874a67b80424742990c218a746f5754b3a2c769a9ecbb457500412b0281ebb4304054067880b5407c24baa40b063e62c1d162c55f4a646edd70607bcbaef3808211db13013780eba4585adb29d3256f8059f81a40517e63b12c41ef7c0a8726a4ba62701e3598',
118
+ '0x9f0d3719f5b0b12c7105c073c507445948cabb800ff6a2c0cf1c6e2dd1cad56d23aa6f51a78d85792606966afc176ecb4101e51b802db7d1beaf4152abcbe2d72358d938f31eef2e6f9adb322dd6316cd211dfe79580bb7fd6b2fa22db69bca4f70304addc539798fc6174ddae0c5865c71ff96e53415c5700bd9a93e85e3ce1d20700002408d6070000dc07000080054bc6bd08b77192f231932a6e63a3f54a48d954725a2198a762781089bf150980fd53aee7d7ccb0767af55024401273b0a9437c5917cdd60d406dac4aab7223338019cbbdbf60cd90027c802d921f737c07a073bb4bed3b9ff0c37b26506e6aafc94c57077a93d174890f1ff20700001404d0070000806e5feeb98858d49ab4f600b9337280df82041595257c4d566175cbf59cc105f680f44d2eba0587ca4f414fe092f163abb43531c554c28cfcc26cf032083a7af9b4',
119
+ '0x9f0d7fefc408aac59dbfe80a72ac8e3ce5cebf80b9cbd0d700a17a0e4c717af58b887e80c0bce7832e64817caa8b47152baf5ba0807e1ee2c8362cd0745aa0c58780b99fefa1024c1b472d3386a2319e71b68028a68012d23785dbec11744e5f0fef2c34efcb738891240cd4ad63bb101bd4c2512a0980152c557d36cdee4289c8b2c42462576e238b62422b257e91773a473f49c3858680a8842b069c158af198d7d570838f69a2f4c9a218d51c69ad60361a873a11bbea80f08851397f0db3ac9785de1017f41cb5b073b92ecf6b4653d1f38d4993028e4680117820f0023f9e54736ad10ecae8806bcf1cc8b4ed694aa530ed85e6361db7ea80be32eae63e4a223cdf5cbf90b66f48665668ec0bedbb6b76302768ea6f3b19cc8030b143a144cc26437db830e7d750f21dbc87cf3140097b1fdbddb697782a237180ec76035be1c7d52a15dcf76aaf69fced1772f1464ec7886952dada14030ad4fc809b912d6aa76e61c4b515535db14d28490924ef2007cf19e0022b5a089b6d010380f28a57be8a23f6a2588595e53cb640bbeeee2ef9ddc962a6672ac98bd2d6ea4e',
120
+ ];
121
+ const registry = new types_1.TypeRegistry();
122
+ const paraId = registry.createType('u32', 2000);
123
+ const headKey = (0, proof_1.dmqMqcHead)(paraId);
124
+ const upgradeKey = (0, proof_1.upgradeGoAheadSignal)(paraId);
125
+ const ingressChannelIndexKey = (0, proof_1.hrmpIngressChannelIndex)(paraId);
126
+ const egressChannelIndexKey = (0, proof_1.hrmpEgressChannelIndex)(paraId);
127
+ const originalDecoded = await (0, executor_1.decodeProof)(ROOT_TRIE_HASH, [headKey, upgradeKey, ingressChannelIndexKey, egressChannelIndexKey, ...Object.values(proof_1.WELL_KNOWN_KEYS)], NODES);
128
+ (0, vitest_1.expect)(originalDecoded).toMatchSnapshot();
129
+ (0, vitest_1.expect)(originalDecoded[upgradeKey]).toBeUndefined();
130
+ const config = registry.createType('HostConfiguration', originalDecoded[proof_1.WELL_KNOWN_KEYS.ACTIVE_CONFIG]);
131
+ (0, vitest_1.expect)(config.toJSON()).toMatchSnapshot();
132
+ const goAhead = registry.createType('UpgradeGoAhead', 'GoAhead');
133
+ const { trieRootHash, nodes } = await (0, executor_1.createProof)(ROOT_TRIE_HASH, NODES, [
134
+ [proof_1.WELL_KNOWN_KEYS.ACTIVE_CONFIG, config.toHex()],
135
+ [upgradeKey, goAhead.toHex()],
136
+ ]);
137
+ (0, vitest_1.expect)(trieRootHash).toMatchSnapshot();
138
+ (0, vitest_1.expect)(nodes).toMatchSnapshot();
139
+ const decoded = await (0, executor_1.decodeProof)(trieRootHash, [headKey, upgradeKey, ingressChannelIndexKey, egressChannelIndexKey, ...Object.values(proof_1.WELL_KNOWN_KEYS)], nodes);
140
+ (0, vitest_1.expect)(decoded).toMatchSnapshot();
141
+ (0, vitest_1.expect)(decoded[upgradeKey]).toBe('0x01');
142
+ });
58
143
  });
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import '@polkadot/types-codec';
2
+ import { ProviderInterface } from '@polkadot/rpc-provider/types';
2
3
  import { Api } from './api';
3
4
  import { Blockchain } from './blockchain';
4
5
  import { Config } from './schema';
5
- import { ProviderInterface } from '@polkadot/rpc-provider/types';
6
6
  import { TaskManager } from './task';
7
7
  export declare const setup: (argv: Config) => Promise<{
8
8
  chain: Blockchain;
@@ -10,4 +10,12 @@ export declare const setup: (argv: Config) => Promise<{
10
10
  ws: ProviderInterface;
11
11
  tasks: TaskManager;
12
12
  }>;
13
- export declare const runBlock: (argv: any) => Promise<void>;
13
+ export declare const setupWithServer: (argv: Config) => Promise<{
14
+ close: () => Promise<void>;
15
+ chain: Blockchain;
16
+ api: Api;
17
+ ws: ProviderInterface;
18
+ tasks: TaskManager;
19
+ }>;
20
+ export declare const runBlock: (argv: Config) => Promise<void>;
21
+ export declare const decodeKey: (argv: any) => Promise<void>;
package/dist/index.js CHANGED
@@ -3,40 +3,40 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.runBlock = exports.setup = void 0;
6
+ exports.decodeKey = exports.runBlock = exports.setupWithServer = exports.setup = void 0;
7
7
  require("@polkadot/types-codec");
8
- const api_1 = require("./api");
8
+ const api_1 = require("@polkadot/api");
9
+ const util_1 = require("@polkadot/util");
10
+ const helpers_1 = require("yargs/helpers");
11
+ const node_fs_1 = require("node:fs");
12
+ const js_yaml_1 = __importDefault(require("js-yaml"));
13
+ const yargs_1 = __importDefault(require("yargs"));
14
+ const api_2 = require("./api");
9
15
  const blockchain_1 = require("./blockchain");
10
16
  const txpool_1 = require("./blockchain/txpool");
11
17
  const schema_1 = require("./schema");
12
18
  const genesis_provider_1 = require("./genesis-provider");
13
19
  const inherents_1 = require("./blockchain/inherents");
14
20
  const task_1 = require("./task");
15
- const api_2 = require("@polkadot/api");
16
21
  const server_1 = require("./server");
17
22
  const logger_1 = require("./logger");
18
23
  const rpc_1 = require("./rpc");
19
- const helpers_1 = require("yargs/helpers");
20
24
  const import_storage_1 = require("./utils/import-storage");
21
25
  const db_1 = require("./db");
22
- const node_fs_1 = require("node:fs");
23
- const js_yaml_1 = __importDefault(require("js-yaml"));
24
- const yargs_1 = __importDefault(require("yargs"));
25
26
  const setup = async (argv) => {
26
- const port = argv.port || Number(process.env.PORT) || 8000;
27
- let wsProvider;
27
+ let provider;
28
28
  if (argv.genesis) {
29
29
  if (typeof argv.genesis === 'string') {
30
- wsProvider = await genesis_provider_1.GenesisProvider.fromUrl(argv.genesis);
30
+ provider = await genesis_provider_1.GenesisProvider.fromUrl(argv.genesis);
31
31
  }
32
32
  else {
33
- wsProvider = new genesis_provider_1.GenesisProvider(argv.genesis);
33
+ provider = new genesis_provider_1.GenesisProvider(argv.genesis);
34
34
  }
35
35
  }
36
36
  else {
37
- wsProvider = new api_2.WsProvider(argv.endpoint);
37
+ provider = new api_1.WsProvider(argv.endpoint);
38
38
  }
39
- const api = new api_1.Api(wsProvider);
39
+ const api = new api_2.Api(provider);
40
40
  await api.isReady;
41
41
  let blockHash;
42
42
  if (argv.block == null) {
@@ -54,8 +54,13 @@ const setup = async (argv) => {
54
54
  db = await (0, db_1.openDb)(argv.db);
55
55
  }
56
56
  const header = await api.getHeader(blockHash);
57
+ const port = argv.port || Number(process.env.PORT) || 8000;
57
58
  const tasks = new task_1.TaskManager(port, argv['mock-signature-host'], argv['executor-cmd']);
58
- const setTimestamp = new inherents_1.SetTimestamp();
59
+ const blockNumber = +header.number;
60
+ const timestamp = argv.timestamp ?? Date.now();
61
+ const setTimestamp = new inherents_1.SetTimestamp((newBlockNumber) => {
62
+ return timestamp + (newBlockNumber - blockNumber) * 12000; // TODO: make this more flexible
63
+ });
59
64
  const inherents = new inherents_1.InherentProviders(setTimestamp, [new inherents_1.SetValidationData(tasks, 1)]);
60
65
  const chain = new blockchain_1.Blockchain({
61
66
  api,
@@ -68,20 +73,29 @@ const setup = async (argv) => {
68
73
  number: Number(header.number),
69
74
  },
70
75
  });
71
- const context = { chain, api, ws: wsProvider, tasks };
72
- const listeningPort = await (0, server_1.createServer)(port, (0, rpc_1.handler)(context)).port;
73
- tasks.updateListeningPort(listeningPort);
76
+ const context = { chain, api, ws: provider, tasks };
74
77
  await (0, import_storage_1.importStorage)(chain, argv['import-storage']);
75
78
  await (0, import_storage_1.overrideWasm)(chain, argv['wasm-override']);
79
+ return context;
80
+ };
81
+ exports.setup = setup;
82
+ const setupWithServer = async (argv) => {
83
+ const context = await (0, exports.setup)(argv);
84
+ const port = argv.port || Number(process.env.PORT) || 8000;
85
+ const { port: listeningPort, close } = (0, server_1.createServer)(port, (0, rpc_1.handler)(context));
86
+ context.tasks.updateListeningPort(await listeningPort);
76
87
  if (argv.genesis) {
77
88
  // mine 1st block when starting from genesis to set some mock validation data
78
- await chain.newBlock();
89
+ await context.chain.newBlock();
79
90
  }
80
- return context;
91
+ return {
92
+ ...context,
93
+ close,
94
+ };
81
95
  };
82
- exports.setup = setup;
96
+ exports.setupWithServer = setupWithServer;
83
97
  const runBlock = async (argv) => {
84
- const context = await (0, exports.setup)(argv);
98
+ const context = await (0, exports.setupWithServer)(argv);
85
99
  const header = await context.chain.head.header;
86
100
  const parent = header.parentHash.toHex();
87
101
  const wasm = await context.chain.head.wasm;
@@ -105,9 +119,28 @@ const runBlock = async (argv) => {
105
119
  console.dir(output, { depth: null, colors: false });
106
120
  }
107
121
  });
122
+ await context.close();
108
123
  setTimeout(() => process.exit(0), 50);
109
124
  };
110
125
  exports.runBlock = runBlock;
126
+ const decodeKey = async (argv) => {
127
+ const context = await (0, exports.setup)(argv);
128
+ const key = argv.key;
129
+ const meta = await context.chain.head.meta;
130
+ outer: for (const module of Object.values(meta.query)) {
131
+ for (const storage of Object.values(module)) {
132
+ const keyPrefix = (0, util_1.u8aToHex)(storage.keyPrefix());
133
+ if (key.startsWith(keyPrefix)) {
134
+ const decodedKey = meta.registry.createType('StorageKey', key);
135
+ decodedKey.setMeta(storage.meta);
136
+ console.log(`${storage.section}.${storage.method}`, decodedKey.args.map((x) => x.toHuman()).join(', '));
137
+ break outer;
138
+ }
139
+ }
140
+ }
141
+ setTimeout(() => process.exit(0), 50);
142
+ };
143
+ exports.decodeKey = decodeKey;
111
144
  const processConfig = (argv) => {
112
145
  if (argv.config) {
113
146
  const configFile = (0, node_fs_1.readFileSync)(argv.config, 'utf8');
@@ -117,12 +150,7 @@ const processConfig = (argv) => {
117
150
  }
118
151
  return argv;
119
152
  };
120
- (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
121
- .command('run-block', 'Replay a block', (yargs) => yargs.options({
122
- port: {
123
- desc: 'Port to listen on',
124
- number: true,
125
- },
153
+ const defaultOptions = {
126
154
  endpoint: {
127
155
  desc: 'Endpoint to connect to',
128
156
  string: true,
@@ -131,26 +159,35 @@ const processConfig = (argv) => {
131
159
  desc: 'Block hash or block number. Default to latest block',
132
160
  string: true,
133
161
  },
134
- 'executor-cmd': {
135
- desc: 'Command to execute the executor',
136
- string: true,
137
- },
138
- 'output-path': {
139
- desc: 'File path to print output',
162
+ 'wasm-override': {
163
+ desc: 'Path to wasm override',
140
164
  string: true,
141
165
  },
142
166
  db: {
143
167
  desc: 'Path to database',
144
168
  string: true,
145
169
  },
146
- 'wasm-override': {
147
- desc: 'Path to wasm override',
148
- string: true,
149
- },
150
170
  config: {
151
171
  desc: 'Path to config file',
152
172
  string: true,
153
173
  },
174
+ };
175
+ (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
176
+ .scriptName('chopsticks')
177
+ .command('run-block', 'Replay a block', (yargs) => yargs.options({
178
+ ...defaultOptions,
179
+ port: {
180
+ desc: 'Port to listen on',
181
+ number: true,
182
+ },
183
+ 'executor-cmd': {
184
+ desc: 'Command to execute the executor',
185
+ string: true,
186
+ },
187
+ 'output-path': {
188
+ desc: 'File path to print output',
189
+ string: true,
190
+ },
154
191
  }), (argv) => {
155
192
  (0, exports.runBlock)(processConfig(argv)).catch((err) => {
156
193
  console.error(err);
@@ -158,18 +195,11 @@ const processConfig = (argv) => {
158
195
  });
159
196
  })
160
197
  .command('dev', 'Dev mode', (yargs) => yargs.options({
198
+ ...defaultOptions,
161
199
  port: {
162
200
  desc: 'Port to listen on',
163
201
  number: true,
164
202
  },
165
- endpoint: {
166
- desc: 'Endpoint to connect to',
167
- string: true,
168
- },
169
- block: {
170
- desc: 'Block hash or block number. Default to latest block',
171
- string: true,
172
- },
173
203
  'executor-cmd': {
174
204
  desc: 'Command to execute the executor',
175
205
  string: true,
@@ -186,23 +216,25 @@ const processConfig = (argv) => {
186
216
  desc: 'Mock signature host so any signature starts with 0xdeadbeef and filled by 0xcd is considered valid',
187
217
  boolean: true,
188
218
  },
189
- db: {
190
- desc: 'Path to database',
191
- string: true,
192
- },
193
- 'wasm-override': {
194
- desc: 'Path to wasm override',
195
- string: true,
196
- },
197
- config: {
198
- desc: 'Path to config file',
199
- string: true,
200
- },
201
219
  }), (argv) => {
202
- (0, exports.setup)(processConfig(argv)).catch((err) => {
220
+ (0, exports.setupWithServer)(processConfig(argv)).catch((err) => {
221
+ console.error(err);
222
+ process.exit(1);
223
+ });
224
+ })
225
+ .command('decode-key <key>', 'Deocde a key', (yargs) => yargs
226
+ .positional('key', {
227
+ desc: 'Key to decode',
228
+ type: 'string',
229
+ })
230
+ .options({
231
+ ...defaultOptions,
232
+ }), (argv) => {
233
+ (0, exports.decodeKey)(processConfig(argv)).catch((err) => {
203
234
  console.error(err);
204
235
  process.exit(1);
205
236
  });
206
237
  })
207
238
  .strict()
208
- .help().argv;
239
+ .help()
240
+ .alias('help', 'h').argv;
@@ -38,5 +38,6 @@ const handlers = {
38
38
  author_unwatchExtrinsic: async (_context, [subid], { unsubscribe }) => {
39
39
  unsubscribe(subid);
40
40
  },
41
+ author_pendingExtrinsics: async (_context) => [],
41
42
  };
42
43
  exports.default = handlers;
@@ -131,7 +131,10 @@ export declare const configSchema: z.ZodObject<{
131
131
  };
132
132
  };
133
133
  }>]>>;
134
+ timestamp: z.ZodOptional<z.ZodNumber>;
134
135
  }, "strict", z.ZodTypeAny, {
136
+ port?: number | undefined;
137
+ timestamp?: number | undefined;
135
138
  db?: string | undefined;
136
139
  genesis?: string | {
137
140
  name: string;
@@ -147,7 +150,6 @@ export declare const configSchema: z.ZodObject<{
147
150
  };
148
151
  };
149
152
  } | undefined;
150
- port?: number | undefined;
151
153
  endpoint?: string | undefined;
152
154
  block?: string | number | undefined;
153
155
  'executor-cmd'?: string | undefined;
@@ -156,6 +158,8 @@ export declare const configSchema: z.ZodObject<{
156
158
  'mock-signature-host'?: boolean | undefined;
157
159
  'wasm-override'?: string | undefined;
158
160
  }, {
161
+ port?: number | undefined;
162
+ timestamp?: number | undefined;
159
163
  db?: string | undefined;
160
164
  genesis?: string | {
161
165
  name: string;
@@ -171,7 +175,6 @@ export declare const configSchema: z.ZodObject<{
171
175
  };
172
176
  };
173
177
  } | undefined;
174
- port?: number | undefined;
175
178
  endpoint?: string | undefined;
176
179
  block?: string | number | undefined;
177
180
  'executor-cmd'?: string | undefined;
@@ -25,5 +25,6 @@ exports.configSchema = zod_1.z
25
25
  db: zod_1.z.string().optional(),
26
26
  'wasm-override': zod_1.z.string().optional(),
27
27
  genesis: zod_1.z.union([zod_1.z.string(), exports.genesisSchema]).optional(),
28
+ timestamp: zod_1.z.number().optional(),
28
29
  })
29
30
  .strict();
package/dist/task.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export interface TaskResponseCall {
2
2
  Call: {
3
- result: string;
4
- storageDiff: [string, string | null][];
3
+ result: `0x${string}}`;
4
+ storageDiff: [`0x${string}}`, `0x${string}}` | null][];
5
5
  };
6
6
  }
7
7
  export interface TaskResponseError {
package/dist/task.js CHANGED
@@ -29,6 +29,7 @@ class TaskManager {
29
29
  addTask(task, callback = () => { }) {
30
30
  logger.debug({
31
31
  kind: Object.keys(task)[0],
32
+ port: this.#listeningPort,
32
33
  }, 'AddTask');
33
34
  if ('Call' in task && task.Call.mockSignatureHost === undefined) {
34
35
  task.Call.mockSignatureHost = this.#mockSignatureHost;
@@ -0,0 +1,7 @@
1
+ import { HexString } from '@polkadot/util/types';
2
+ import { u32 } from '@polkadot/types';
3
+ export declare const WELL_KNOWN_KEYS: Record<string, HexString>;
4
+ export declare const dmqMqcHead: (paraId: u32) => `0x${string}`;
5
+ export declare const upgradeGoAheadSignal: (paraId: u32) => `0x${string}`;
6
+ export declare const hrmpIngressChannelIndex: (paraId: u32) => `0x${string}`;
7
+ export declare const hrmpEgressChannelIndex: (paraId: u32) => `0x${string}`;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hrmpEgressChannelIndex = exports.hrmpIngressChannelIndex = exports.upgradeGoAheadSignal = exports.dmqMqcHead = exports.WELL_KNOWN_KEYS = void 0;
4
+ const util_1 = require("@polkadot/util");
5
+ const util_crypto_1 = require("@polkadot/util-crypto");
6
+ exports.WELL_KNOWN_KEYS = {
7
+ EPOCH_INDEX: '0x1cb6f36e027abb2091cfb5110ab5087f38316cbf8fa0da822a20ac1c55bf1be3',
8
+ CURRENT_BLOCK_RANDOMNESS: '0x1cb6f36e027abb2091cfb5110ab5087fd077dfdb8adb10f78f10a5df8742c545',
9
+ ONE_EPOCH_AGO_RANDOMNESS: '0x1cb6f36e027abb2091cfb5110ab5087f7ce678799d3eff024253b90e84927cc6',
10
+ TWO_EPOCHS_AGO_RANDOMNESS: '0x1cb6f36e027abb2091cfb5110ab5087f7a414cb008e0e61e46722aa60abdd672',
11
+ CURRENT_SLOT: '0x1cb6f36e027abb2091cfb5110ab5087f06155b3cd9a8c9e5e9a23fd5dc13a5ed',
12
+ ACTIVE_CONFIG: '0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385',
13
+ };
14
+ const prefixWithParaId = (prefix, paraId) => {
15
+ const id = paraId.toU8a();
16
+ return (0, util_1.u8aToHex)((0, util_1.u8aConcat)((0, util_1.hexToU8a)(prefix), (0, util_crypto_1.xxhashAsU8a)(id, 64), id));
17
+ };
18
+ const dmqMqcHead = (paraId) => {
19
+ const prefix = '0x63f78c98723ddc9073523ef3beefda0c4d7fefc408aac59dbfe80a72ac8e3ce5';
20
+ return prefixWithParaId(prefix, paraId);
21
+ };
22
+ exports.dmqMqcHead = dmqMqcHead;
23
+ const upgradeGoAheadSignal = (paraId) => {
24
+ const prefix = '0xcd710b30bd2eab0352ddcc26417aa1949e94c040f5e73d9b7addd6cb603d15d3';
25
+ return prefixWithParaId(prefix, paraId);
26
+ };
27
+ exports.upgradeGoAheadSignal = upgradeGoAheadSignal;
28
+ const hrmpIngressChannelIndex = (paraId) => {
29
+ const prefix = '0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948';
30
+ return prefixWithParaId(prefix, paraId);
31
+ };
32
+ exports.hrmpIngressChannelIndex = hrmpIngressChannelIndex;
33
+ const hrmpEgressChannelIndex = (paraId) => {
34
+ const prefix = '0x6a0da05ca59913bc38a8630590f2627cf12b746dcf32e843354583c9702cc020';
35
+ return prefixWithParaId(prefix, paraId);
36
+ };
37
+ exports.hrmpEgressChannelIndex = hrmpEgressChannelIndex;
@@ -49,7 +49,7 @@ const setStorage = async (chain, storage, blockHash) => {
49
49
  storageItems = storage;
50
50
  }
51
51
  else {
52
- storageItems = objectToStorageItems(await block.meta, storage);
52
+ storageItems = objectToStorageItems(await block.withAvoidTasks(() => block.meta), storage);
53
53
  }
54
54
  block.pushStorageLayer().setAll(storageItems);
55
55
  return block.hash;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acala-network/chopsticks",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Bryan Chen <xlchen1291@gmail.com>",
@@ -28,7 +28,7 @@
28
28
  "dev:acala": "ts-node-dev --transpile-only --inspect --notify=false src/index.ts -- dev --config=configs/acala.yml"
29
29
  },
30
30
  "dependencies": {
31
- "@acala-network/chopsticks-executor": "0.2.0",
31
+ "@acala-network/chopsticks-executor": "0.2.2",
32
32
  "@polkadot/api": "^9.10.1",
33
33
  "@polkadot/rpc-provider": "^9.10.1",
34
34
  "@polkadot/types": "^9.10.1",