@acala-network/chopsticks 0.5.9 → 0.5.10

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.
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dryRunInherents = exports.dryRunExtrinsic = exports.buildBlock = exports.newHeader = void 0;
4
4
  const block_1 = require("./block");
5
- const util_crypto_1 = require("@polkadot/util-crypto");
5
+ const storage_layer_1 = require("./storage-layer");
6
6
  const util_1 = require("@polkadot/util");
7
7
  const utils_1 = require("../utils");
8
8
  const logger_1 = require("../logger");
@@ -90,12 +90,16 @@ const newHeader = async (head) => {
90
90
  return header;
91
91
  };
92
92
  exports.newHeader = newHeader;
93
- const initNewBlock = async (head, header, inherents) => {
93
+ const initNewBlock = async (head, header, inherents, storageLayer) => {
94
94
  const blockNumber = header.number.toNumber();
95
95
  const hash = `0x${Math.round(Math.random() * 100000000)
96
96
  .toString(16)
97
97
  .padEnd(64, '0')}`;
98
- const newBlock = new block_1.Block(head.chain, blockNumber, hash, head, { header, extrinsics: [], storage: head.storage });
98
+ const newBlock = new block_1.Block(head.chain, blockNumber, hash, head, {
99
+ header,
100
+ extrinsics: [],
101
+ storage: storageLayer ?? head.storage,
102
+ });
99
103
  {
100
104
  // initialize block
101
105
  const { storageDiff } = await newBlock.call('Core_initialize_block', [header.toHex()]);
@@ -125,18 +129,11 @@ const initNewBlock = async (head, header, inherents) => {
125
129
  const buildBlock = async (head, inherents, extrinsics, ump, onApplyExtrinsicError) => {
126
130
  const registry = await head.registry;
127
131
  const header = await (0, exports.newHeader)(head);
128
- const { block: newBlock } = await initNewBlock(head, header, inherents);
129
- logger.info({
130
- number: newBlock.number,
131
- extrinsicsCount: extrinsics.length,
132
- tempHash: newBlock.hash,
133
- }, `Try building block #${newBlock.number.toLocaleString()}`);
134
- const pendingExtrinsics = [];
135
- const includedExtrinsic = [];
132
+ let layer;
136
133
  // apply ump via storage override hack
137
134
  if (Object.keys(ump).length > 0) {
138
135
  const meta = await head.meta;
139
- const layer = head.pushStorageLayer();
136
+ layer = new storage_layer_1.StorageLayer(head.storage);
140
137
  for (const [paraId, upwardMessages] of Object.entries(ump)) {
141
138
  const queueSize = meta.registry.createType('(u32, u32)', [
142
139
  upwardMessages.length,
@@ -148,15 +145,20 @@ const buildBlock = async (head, inherents, extrinsics, ump, onApplyExtrinsicErro
148
145
  [(0, utils_1.compactHex)(meta.query.ump.relayDispatchQueues(paraId)), messages.toHex()],
149
146
  [(0, utils_1.compactHex)(meta.query.ump.relayDispatchQueueSize(paraId)), queueSize.toHex()],
150
147
  ]);
148
+ logger.trace({ paraId, upwardMessages: (0, logger_1.truncate)(upwardMessages) }, 'Pushed UMP');
151
149
  }
152
- logger.trace({
153
- number: newBlock.number,
154
- tempHash: newBlock.hash,
155
- ump,
156
- }, 'Upward messages');
157
150
  const needsDispatch = meta.registry.createType('Vec<u32>', Object.keys(ump));
158
151
  layer.set((0, utils_1.compactHex)(meta.query.ump.needsDispatch()), needsDispatch.toHex());
159
152
  }
153
+ const { block: newBlock } = await initNewBlock(head, header, inherents, layer);
154
+ logger.info({
155
+ number: newBlock.number,
156
+ extrinsicsCount: extrinsics.length,
157
+ umpCount: Object.keys(ump).length,
158
+ tempHash: newBlock.hash,
159
+ }, `Try building block #${newBlock.number.toLocaleString()}`);
160
+ const pendingExtrinsics = [];
161
+ const includedExtrinsic = [];
160
162
  // apply extrinsics
161
163
  for (const extrinsic of extrinsics) {
162
164
  try {
@@ -194,11 +196,12 @@ const buildBlock = async (head, inherents, extrinsics, ump, onApplyExtrinsicErro
194
196
  storageDiff,
195
197
  });
196
198
  logger.info({
197
- hash: finalBlock.hash,
198
- extrinsics: includedExtrinsic.map((x) => (0, util_crypto_1.blake2AsHex)(x, 256)),
199
- pendingExtrinsics: pendingExtrinsics.length,
200
199
  number: newBlock.number,
201
- }, `Block built #${newBlock.number.toLocaleString()} hash ${finalBlock.hash}`);
200
+ hash: finalBlock.hash,
201
+ extrinsics: (0, logger_1.truncate)(includedExtrinsic),
202
+ pendingExtrinsicsCount: pendingExtrinsics.length,
203
+ ump: (0, logger_1.truncate)(ump),
204
+ }, 'Block built');
202
205
  return [finalBlock, pendingExtrinsics];
203
206
  };
204
207
  exports.buildBlock = buildBlock;
@@ -8,6 +8,8 @@ const node_stream_1 = require("node:stream");
8
8
  const lodash_1 = __importDefault(require("lodash"));
9
9
  const utils_1 = require("../utils");
10
10
  const block_builder_1 = require("./block-builder");
11
+ const logger_1 = require("../logger");
12
+ const logger = logger_1.defaultLogger.child({ name: 'txpool' });
11
13
  exports.APPLY_EXTRINSIC_ERROR = 'TxPool::ApplyExtrinsicError';
12
14
  var BuildBlockMode;
13
15
  (function (BuildBlockMode) {
@@ -38,6 +40,7 @@ class TxPool {
38
40
  return this.#pool.filter(({ signer }) => signer === address).map(({ extrinsic }) => extrinsic);
39
41
  }
40
42
  async submitExtrinsic(extrinsic) {
43
+ logger.debug({ extrinsic: (0, logger_1.truncate)(extrinsic) }, 'submit extrinsic');
41
44
  this.#pool.push({ extrinsic, signer: await this.#getSigner(extrinsic) });
42
45
  this.#maybeBuildBlock();
43
46
  }
@@ -47,6 +50,7 @@ class TxPool {
47
50
  return tx.signer.toString();
48
51
  }
49
52
  submitUpwardMessages(id, ump) {
53
+ logger.debug({ id, ump: (0, logger_1.truncate)(ump) }, 'submit upward messages');
50
54
  if (!this.#ump[id]) {
51
55
  this.#ump[id] = [];
52
56
  }
@@ -54,10 +58,12 @@ class TxPool {
54
58
  this.#maybeBuildBlock();
55
59
  }
56
60
  submitDownwardMessages(dmp) {
61
+ logger.debug({ dmp: (0, logger_1.truncate)(dmp) }, 'submit downward messages');
57
62
  this.#dmp.push(...dmp);
58
63
  this.#maybeBuildBlock();
59
64
  }
60
65
  submitHorizontalMessages(id, hrmp) {
66
+ logger.debug({ id, hrmp: (0, logger_1.truncate)(hrmp) }, 'submit horizontal messages');
61
67
  if (!this.#hrmp[id]) {
62
68
  this.#hrmp[id] = [];
63
69
  }
@@ -136,6 +142,7 @@ class TxPool {
136
142
  throw new Error('Unreachable');
137
143
  }
138
144
  const { params, deferred } = pending;
145
+ logger.trace({ params }, 'build block');
139
146
  const head = this.#chain.head;
140
147
  const inherents = await this.#inherentProvider.createInherents(head, params);
141
148
  const [newBlock, pendingExtrinsics] = await (0, block_builder_1.buildBlock)(head, inherents, params.transactions, params.upwardMessages, (extrinsic, error) => {
package/lib/cli.js CHANGED
@@ -15,6 +15,7 @@ const dry_run_1 = require("./dry-run");
15
15
  const dry_run_preimage_1 = require("./dry-run-preimage");
16
16
  const utils_1 = require("./utils");
17
17
  const run_block_1 = require("./run-block");
18
+ const try_runtime_1 = require("./try-runtime");
18
19
  const processConfig = async (path) => {
19
20
  let file;
20
21
  if ((0, utils_1.isUrl)(path)) {
@@ -59,14 +60,14 @@ const defaultOptions = {
59
60
  .scriptName('chopsticks')
60
61
  .command('run-block', 'Replay a block', (yargs) => yargs.options({
61
62
  ...defaultOptions,
62
- port: {
63
- desc: 'Port to listen on',
64
- number: true,
65
- },
66
63
  'output-path': {
67
64
  desc: 'File path to print output',
68
65
  string: true,
69
66
  },
67
+ 'import-storage': {
68
+ desc: 'Pre-defined JSON/YAML storage file path',
69
+ string: true,
70
+ },
70
71
  html: {
71
72
  desc: 'Generate html with storage diff',
72
73
  },
@@ -75,6 +76,26 @@ const defaultOptions = {
75
76
  },
76
77
  }), async (argv) => {
77
78
  await (0, run_block_1.runBlock)(await processArgv(argv));
79
+ })
80
+ .command('try-runtime', 'Runs runtime upgrade', (yargs) => yargs.options({
81
+ ...defaultOptions,
82
+ 'wasm-override': {
83
+ desc: 'Path to WASM built with feature `try-runtime` enabled',
84
+ string: true,
85
+ required: true,
86
+ },
87
+ 'output-path': {
88
+ desc: 'File path to print output',
89
+ string: true,
90
+ },
91
+ html: {
92
+ desc: 'Generate html with storage diff',
93
+ },
94
+ open: {
95
+ desc: 'Open generated html',
96
+ },
97
+ }), async (argv) => {
98
+ await (0, try_runtime_1.tryRuntime)(await processArgv(argv));
78
99
  })
79
100
  .command('dry-run', 'Dry run an extrinsic', (yargs) => yargs.options({
80
101
  ...defaultOptions,
package/lib/run-block.js CHANGED
@@ -7,7 +7,7 @@ const open_html_1 = require("./utils/open-html");
7
7
  const executor_1 = require("./executor");
8
8
  const setup_1 = require("./setup");
9
9
  const runBlock = async (argv) => {
10
- const context = await (0, setup_1.setup)(argv);
10
+ const context = await (0, setup_1.setup)(argv, true);
11
11
  const header = await context.chain.head.header;
12
12
  const wasm = await context.chain.head.wasm;
13
13
  const block = context.chain.head;
package/lib/server.js CHANGED
@@ -137,7 +137,7 @@ const createServer = async (handler, port) => {
137
137
  send({
138
138
  id: req.id,
139
139
  jsonrpc: '2.0',
140
- result: resp || null,
140
+ result: resp ?? null,
141
141
  });
142
142
  }
143
143
  catch (e) {
package/lib/setup.d.ts CHANGED
@@ -3,7 +3,7 @@ import { ProviderInterface } from '@polkadot/rpc-provider/types';
3
3
  import { Api } from './api';
4
4
  import { Blockchain } from './blockchain';
5
5
  import { Config } from './schema';
6
- export declare const setup: (argv: Config) => Promise<{
6
+ export declare const setup: (argv: Config, runBlock?: boolean) => Promise<{
7
7
  chain: Blockchain;
8
8
  api: Api;
9
9
  ws: ProviderInterface;
package/lib/setup.js CHANGED
@@ -11,7 +11,7 @@ const logger_1 = require("./logger");
11
11
  const import_storage_1 = require("./utils/import-storage");
12
12
  const db_1 = require("./db");
13
13
  const time_travel_1 = require("./utils/time-travel");
14
- const setup = async (argv) => {
14
+ const setup = async (argv, runBlock = false) => {
15
15
  let provider;
16
16
  if (argv.genesis) {
17
17
  if (typeof argv.genesis === 'string') {
@@ -66,10 +66,18 @@ const setup = async (argv) => {
66
66
  });
67
67
  if (argv.timestamp)
68
68
  await (0, time_travel_1.timeTravel)(chain, argv.timestamp);
69
+ let at;
70
+ if (runBlock) {
71
+ // in case of run block we need to apply wasm-override and import-storage to parent block
72
+ const block = await chain.head.parentBlock;
73
+ if (!block)
74
+ throw new Error('Cannot find parent block');
75
+ at = block.hash;
76
+ }
69
77
  // override wasm before importing storage, in case new pallets have been
70
78
  // added that have storage imports
71
- await (0, import_storage_1.overrideWasm)(chain, argv['wasm-override']);
72
- await (0, import_storage_1.importStorage)(chain, argv['import-storage']);
79
+ await (0, import_storage_1.overrideWasm)(chain, argv['wasm-override'], at);
80
+ await (0, import_storage_1.importStorage)(chain, argv['import-storage'], at);
73
81
  return { chain, api, ws: provider };
74
82
  };
75
83
  exports.setup = setup;
@@ -0,0 +1,2 @@
1
+ import { Config } from './schema';
2
+ export declare const tryRuntime: (argv: Config) => Promise<never>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tryRuntime = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const generate_html_diff_1 = require("./utils/generate-html-diff");
6
+ const open_html_1 = require("./utils/open-html");
7
+ const setup_1 = require("./setup");
8
+ const tryRuntime = async (argv) => {
9
+ const context = await (0, setup_1.setup)(argv);
10
+ const block = context.chain.head;
11
+ const registry = await block.registry;
12
+ registry.register({
13
+ UpgradeCheckSelect: {
14
+ _enum: {
15
+ None: null,
16
+ },
17
+ },
18
+ });
19
+ const select_none = registry.createType('UpgradeCheckSelect', 'None');
20
+ const result = await block.call('TryRuntime_on_runtime_upgrade', [select_none.toHex()], []);
21
+ if (argv['html']) {
22
+ const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(block, result.storageDiff, block.hash);
23
+ console.log(`Generated preview ${filePath}`);
24
+ if (argv['open']) {
25
+ (0, open_html_1.openHtml)(filePath);
26
+ }
27
+ }
28
+ else if (argv['output-path']) {
29
+ (0, node_fs_1.writeFileSync)(argv['output-path'], JSON.stringify(result, null, 2));
30
+ }
31
+ else {
32
+ console.dir(result, { depth: null, colors: false });
33
+ }
34
+ process.exit(0);
35
+ };
36
+ exports.tryRuntime = tryRuntime;
@@ -1,4 +1,5 @@
1
+ import { HexString } from '@polkadot/util/types';
1
2
  import { Blockchain } from '../blockchain';
2
3
  import { StorageValues } from './set-storage';
3
- export declare const importStorage: (chain: Blockchain, storage?: string | StorageValues) => Promise<void>;
4
- export declare const overrideWasm: (chain: Blockchain, wasmPath?: string) => Promise<void>;
4
+ export declare const importStorage: (chain: Blockchain, storage?: string | StorageValues, at?: HexString) => Promise<void>;
5
+ export declare const overrideWasm: (chain: Blockchain, wasmPath?: string, at?: HexString) => Promise<void>;
@@ -8,7 +8,7 @@ const node_fs_1 = require("node:fs");
8
8
  const js_yaml_1 = __importDefault(require("js-yaml"));
9
9
  const set_storage_1 = require("./set-storage");
10
10
  const logger_1 = require("../logger");
11
- const importStorage = async (chain, storage) => {
11
+ const importStorage = async (chain, storage, at) => {
12
12
  if (storage == null) {
13
13
  return;
14
14
  }
@@ -21,11 +21,11 @@ const importStorage = async (chain, storage) => {
21
21
  else {
22
22
  storageValue = storage;
23
23
  }
24
- const blockHash = await (0, set_storage_1.setStorage)(chain, storageValue);
24
+ const blockHash = await (0, set_storage_1.setStorage)(chain, storageValue, at);
25
25
  logger_1.defaultLogger.trace({ blockHash, storage }, 'ImportStorage');
26
26
  };
27
27
  exports.importStorage = importStorage;
28
- const overrideWasm = async (chain, wasmPath) => {
28
+ const overrideWasm = async (chain, wasmPath, at) => {
29
29
  if (wasmPath == null) {
30
30
  return;
31
31
  }
@@ -38,6 +38,14 @@ const overrideWasm = async (chain, wasmPath) => {
38
38
  else {
39
39
  wasmHex = '0x' + wasm.toString('hex');
40
40
  }
41
- chain.head.setWasm(wasmHex);
41
+ if (at) {
42
+ const block = await chain.getBlock(at);
43
+ if (!block)
44
+ throw new Error(`Cannot find block ${at}`);
45
+ block.setWasm(wasmHex);
46
+ }
47
+ else {
48
+ chain.head.setWasm(wasmHex);
49
+ }
42
50
  };
43
51
  exports.overrideWasm = overrideWasm;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@acala-network/chopsticks",
3
- "version": "0.5.9",
3
+ "version": "0.5.10",
4
4
  "author": "Bryan Chen <xlchen1291@gmail.com>",
5
5
  "license": "Apache-2.0",
6
6
  "bin": "./chopsticks.js",
7
7
  "scripts": {
8
8
  "clean": "rm -rf lib tsconfig.tsbuildinfo",
9
- "build": "yarn clean && tsc -p ./tsconfig.json",
9
+ "build": "tsc -p ./tsconfig.json",
10
10
  "script:start": "cd ../..; ts-node --transpile-only packages/chopsticks/src/cli.ts",
11
11
  "script:run": "LOG_LEVEL=trace ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config=../../configs/dev.yml",
12
12
  "dev:karura": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config=../../configs/karura.yml",
@@ -15,7 +15,7 @@
15
15
  "dev:moonbeam": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config=../../configs/moonbeam.yml"
16
16
  },
17
17
  "dependencies": {
18
- "@acala-network/chopsticks-executor": "0.5.9",
18
+ "@acala-network/chopsticks-executor": "0.5.10",
19
19
  "@polkadot/api": "^9.14.2",
20
20
  "@polkadot/rpc-provider": "^9.14.2",
21
21
  "@polkadot/types": "^9.14.2",