@acala-network/chopsticks 0.5.9 → 0.6.0
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/lib/blockchain/block-builder.js +24 -21
- package/lib/blockchain/block.d.ts +1 -0
- package/lib/blockchain/block.js +7 -1
- package/lib/blockchain/index.d.ts +3 -1
- package/lib/blockchain/index.js +3 -1
- package/lib/blockchain/txpool.d.ts +4 -0
- package/lib/blockchain/txpool.js +26 -0
- package/lib/cli.js +33 -5
- package/lib/dry-run-preimage.js +5 -3
- package/lib/dry-run.js +1 -3
- package/lib/executor.d.ts +1 -0
- package/lib/executor.js +1 -0
- package/lib/genesis-provider.js +1 -0
- package/lib/run-block.js +6 -1
- package/lib/schema/index.d.ts +17 -14
- package/lib/schema/index.js +2 -1
- package/lib/server.js +2 -2
- package/lib/setup.d.ts +1 -1
- package/lib/setup.js +12 -3
- package/lib/try-runtime.d.ts +2 -0
- package/lib/try-runtime.js +36 -0
- package/lib/utils/import-storage.d.ts +3 -2
- package/lib/utils/import-storage.js +12 -4
- package/package.json +24 -24
|
@@ -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
|
|
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, {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
package/lib/blockchain/block.js
CHANGED
|
@@ -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 utils_1 = require("../utils");
|
|
10
|
+
const logger_1 = require("../logger");
|
|
10
11
|
const executor_1 = require("../executor");
|
|
11
12
|
class Block {
|
|
12
13
|
number;
|
|
@@ -172,9 +173,14 @@ class Block {
|
|
|
172
173
|
storage,
|
|
173
174
|
mockSignatureHost: this.#chain.mockSignatureHost,
|
|
174
175
|
allowUnresolvedImports: this.#chain.allowUnresolvedImports,
|
|
176
|
+
runtimeLogLevel: this.#chain.runtimeLogLevel,
|
|
175
177
|
}, (0, executor_1.taskHandler)(this));
|
|
176
|
-
if (response.Call)
|
|
178
|
+
if (response.Call) {
|
|
179
|
+
for (const log of response.Call.runtimeLogs) {
|
|
180
|
+
logger_1.defaultLogger.info(`RuntimeLogs:\n${log}`);
|
|
181
|
+
}
|
|
177
182
|
return response.Call;
|
|
183
|
+
}
|
|
178
184
|
if (response.Error)
|
|
179
185
|
throw Error(response.Error);
|
|
180
186
|
throw Error('Unexpected response');
|
|
@@ -18,6 +18,7 @@ export interface Options {
|
|
|
18
18
|
};
|
|
19
19
|
mockSignatureHost?: boolean;
|
|
20
20
|
allowUnresolvedImports?: boolean;
|
|
21
|
+
runtimeLogLevel?: number;
|
|
21
22
|
registeredTypes: RegisteredTypes;
|
|
22
23
|
}
|
|
23
24
|
export declare class Blockchain {
|
|
@@ -27,9 +28,10 @@ export declare class Blockchain {
|
|
|
27
28
|
readonly db: DataSource | undefined;
|
|
28
29
|
readonly mockSignatureHost: boolean;
|
|
29
30
|
readonly allowUnresolvedImports: boolean;
|
|
31
|
+
readonly runtimeLogLevel: number;
|
|
30
32
|
readonly registeredTypes: RegisteredTypes;
|
|
31
33
|
readonly headState: HeadState;
|
|
32
|
-
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost, allowUnresolvedImports, registeredTypes, }: Options);
|
|
34
|
+
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost, allowUnresolvedImports, runtimeLogLevel, registeredTypes, }: Options);
|
|
33
35
|
get head(): Block;
|
|
34
36
|
get txPool(): TxPool;
|
|
35
37
|
getBlockAt(number?: number): Promise<Block | undefined>;
|
package/lib/blockchain/index.js
CHANGED
|
@@ -16,6 +16,7 @@ class Blockchain {
|
|
|
16
16
|
db;
|
|
17
17
|
mockSignatureHost;
|
|
18
18
|
allowUnresolvedImports;
|
|
19
|
+
runtimeLogLevel;
|
|
19
20
|
registeredTypes;
|
|
20
21
|
#txpool;
|
|
21
22
|
#inherentProvider;
|
|
@@ -24,11 +25,12 @@ class Blockchain {
|
|
|
24
25
|
#blocksByHash = {};
|
|
25
26
|
#loadingBlocks = {};
|
|
26
27
|
headState;
|
|
27
|
-
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost = false, allowUnresolvedImports = false, registeredTypes = {}, }) {
|
|
28
|
+
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost = false, allowUnresolvedImports = false, runtimeLogLevel = 0, registeredTypes = {}, }) {
|
|
28
29
|
this.api = api;
|
|
29
30
|
this.db = db;
|
|
30
31
|
this.mockSignatureHost = mockSignatureHost;
|
|
31
32
|
this.allowUnresolvedImports = allowUnresolvedImports;
|
|
33
|
+
this.runtimeLogLevel = runtimeLogLevel;
|
|
32
34
|
this.registeredTypes = registeredTypes;
|
|
33
35
|
this.#head = new block_1.Block(this, header.number, header.hash);
|
|
34
36
|
this.#registerBlock(this.#head);
|
|
@@ -28,6 +28,10 @@ export declare class TxPool {
|
|
|
28
28
|
readonly event: EventEmitter;
|
|
29
29
|
constructor(chain: Blockchain, inherentProvider: InherentProvider, mode?: BuildBlockMode);
|
|
30
30
|
get pendingExtrinsics(): HexString[];
|
|
31
|
+
get ump(): Record<number, HexString[]>;
|
|
32
|
+
get dmp(): DownwardMessage[];
|
|
33
|
+
get hrmp(): Record<number, HorizontalMessage[]>;
|
|
34
|
+
clear(): void;
|
|
31
35
|
pendingExtrinsicsBy(address: string): HexString[];
|
|
32
36
|
submitExtrinsic(extrinsic: HexString): Promise<void>;
|
|
33
37
|
submitUpwardMessages(id: number, ump: HexString[]): void;
|
package/lib/blockchain/txpool.js
CHANGED
|
@@ -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) {
|
|
@@ -34,10 +36,30 @@ class TxPool {
|
|
|
34
36
|
get pendingExtrinsics() {
|
|
35
37
|
return this.#pool.map(({ extrinsic }) => extrinsic);
|
|
36
38
|
}
|
|
39
|
+
get ump() {
|
|
40
|
+
return this.#ump;
|
|
41
|
+
}
|
|
42
|
+
get dmp() {
|
|
43
|
+
return this.#dmp;
|
|
44
|
+
}
|
|
45
|
+
get hrmp() {
|
|
46
|
+
return this.#hrmp;
|
|
47
|
+
}
|
|
48
|
+
clear() {
|
|
49
|
+
this.#pool.length = 0;
|
|
50
|
+
for (const id of Object.keys(this.#ump)) {
|
|
51
|
+
delete this.#ump[id];
|
|
52
|
+
}
|
|
53
|
+
this.#dmp.length = 0;
|
|
54
|
+
for (const id of Object.keys(this.#hrmp)) {
|
|
55
|
+
delete this.#hrmp[id];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
37
58
|
pendingExtrinsicsBy(address) {
|
|
38
59
|
return this.#pool.filter(({ signer }) => signer === address).map(({ extrinsic }) => extrinsic);
|
|
39
60
|
}
|
|
40
61
|
async submitExtrinsic(extrinsic) {
|
|
62
|
+
logger.debug({ extrinsic: (0, logger_1.truncate)(extrinsic) }, 'submit extrinsic');
|
|
41
63
|
this.#pool.push({ extrinsic, signer: await this.#getSigner(extrinsic) });
|
|
42
64
|
this.#maybeBuildBlock();
|
|
43
65
|
}
|
|
@@ -47,6 +69,7 @@ class TxPool {
|
|
|
47
69
|
return tx.signer.toString();
|
|
48
70
|
}
|
|
49
71
|
submitUpwardMessages(id, ump) {
|
|
72
|
+
logger.debug({ id, ump: (0, logger_1.truncate)(ump) }, 'submit upward messages');
|
|
50
73
|
if (!this.#ump[id]) {
|
|
51
74
|
this.#ump[id] = [];
|
|
52
75
|
}
|
|
@@ -54,10 +77,12 @@ class TxPool {
|
|
|
54
77
|
this.#maybeBuildBlock();
|
|
55
78
|
}
|
|
56
79
|
submitDownwardMessages(dmp) {
|
|
80
|
+
logger.debug({ dmp: (0, logger_1.truncate)(dmp) }, 'submit downward messages');
|
|
57
81
|
this.#dmp.push(...dmp);
|
|
58
82
|
this.#maybeBuildBlock();
|
|
59
83
|
}
|
|
60
84
|
submitHorizontalMessages(id, hrmp) {
|
|
85
|
+
logger.debug({ id, hrmp: (0, logger_1.truncate)(hrmp) }, 'submit horizontal messages');
|
|
61
86
|
if (!this.#hrmp[id]) {
|
|
62
87
|
this.#hrmp[id] = [];
|
|
63
88
|
}
|
|
@@ -136,6 +161,7 @@ class TxPool {
|
|
|
136
161
|
throw new Error('Unreachable');
|
|
137
162
|
}
|
|
138
163
|
const { params, deferred } = pending;
|
|
164
|
+
logger.trace({ params }, 'build block');
|
|
139
165
|
const head = this.#chain.head;
|
|
140
166
|
const inherents = await this.#inherentProvider.createInherents(head, params);
|
|
141
167
|
const [newBlock, pendingExtrinsics] = await (0, block_builder_1.buildBlock)(head, inherents, params.transactions, params.upwardMessages, (extrinsic, error) => {
|
package/lib/cli.js
CHANGED
|
@@ -5,7 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const helpers_1 = require("yargs/helpers");
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
9
|
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
9
11
|
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
10
12
|
const yargs_1 = __importDefault(require("yargs"));
|
|
11
13
|
const _1 = require(".");
|
|
@@ -15,6 +17,8 @@ const dry_run_1 = require("./dry-run");
|
|
|
15
17
|
const dry_run_preimage_1 = require("./dry-run-preimage");
|
|
16
18
|
const utils_1 = require("./utils");
|
|
17
19
|
const run_block_1 = require("./run-block");
|
|
20
|
+
const try_runtime_1 = require("./try-runtime");
|
|
21
|
+
dotenv_1.default.config();
|
|
18
22
|
const processConfig = async (path) => {
|
|
19
23
|
let file;
|
|
20
24
|
if ((0, utils_1.isUrl)(path)) {
|
|
@@ -23,7 +27,7 @@ const processConfig = async (path) => {
|
|
|
23
27
|
else {
|
|
24
28
|
file = (0, node_fs_1.readFileSync)(path, 'utf8');
|
|
25
29
|
}
|
|
26
|
-
const config = js_yaml_1.default.load(file);
|
|
30
|
+
const config = js_yaml_1.default.load(lodash_1.default.template(file, { variable: 'env' })(process.env));
|
|
27
31
|
return schema_1.configSchema.parse(config);
|
|
28
32
|
};
|
|
29
33
|
const processArgv = async (argv) => {
|
|
@@ -54,19 +58,23 @@ const defaultOptions = {
|
|
|
54
58
|
desc: 'Path to config file',
|
|
55
59
|
string: true,
|
|
56
60
|
},
|
|
61
|
+
'runtime-log-level': {
|
|
62
|
+
desc: 'Runtime maximum log level [off = 0; error = 1; warn = 2; info = 3; debug = 4; trace = 5]',
|
|
63
|
+
number: true,
|
|
64
|
+
},
|
|
57
65
|
};
|
|
58
66
|
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
59
67
|
.scriptName('chopsticks')
|
|
60
68
|
.command('run-block', 'Replay a block', (yargs) => yargs.options({
|
|
61
69
|
...defaultOptions,
|
|
62
|
-
port: {
|
|
63
|
-
desc: 'Port to listen on',
|
|
64
|
-
number: true,
|
|
65
|
-
},
|
|
66
70
|
'output-path': {
|
|
67
71
|
desc: 'File path to print output',
|
|
68
72
|
string: true,
|
|
69
73
|
},
|
|
74
|
+
'import-storage': {
|
|
75
|
+
desc: 'Pre-defined JSON/YAML storage file path',
|
|
76
|
+
string: true,
|
|
77
|
+
},
|
|
70
78
|
html: {
|
|
71
79
|
desc: 'Generate html with storage diff',
|
|
72
80
|
},
|
|
@@ -75,6 +83,26 @@ const defaultOptions = {
|
|
|
75
83
|
},
|
|
76
84
|
}), async (argv) => {
|
|
77
85
|
await (0, run_block_1.runBlock)(await processArgv(argv));
|
|
86
|
+
})
|
|
87
|
+
.command('try-runtime', 'Runs runtime upgrade', (yargs) => yargs.options({
|
|
88
|
+
...defaultOptions,
|
|
89
|
+
'wasm-override': {
|
|
90
|
+
desc: 'Path to WASM built with feature `try-runtime` enabled',
|
|
91
|
+
string: true,
|
|
92
|
+
required: true,
|
|
93
|
+
},
|
|
94
|
+
'output-path': {
|
|
95
|
+
desc: 'File path to print output',
|
|
96
|
+
string: true,
|
|
97
|
+
},
|
|
98
|
+
html: {
|
|
99
|
+
desc: 'Generate html with storage diff',
|
|
100
|
+
},
|
|
101
|
+
open: {
|
|
102
|
+
desc: 'Open generated html',
|
|
103
|
+
},
|
|
104
|
+
}), async (argv) => {
|
|
105
|
+
await (0, try_runtime_1.tryRuntime)(await processArgv(argv));
|
|
78
106
|
})
|
|
79
107
|
.command('dry-run', 'Dry run an extrinsic', (yargs) => yargs.options({
|
|
80
108
|
...defaultOptions,
|
package/lib/dry-run-preimage.js
CHANGED
|
@@ -67,10 +67,14 @@ const dryRunPreimage = async (argv) => {
|
|
|
67
67
|
storage: [],
|
|
68
68
|
mockSignatureHost: false,
|
|
69
69
|
allowUnresolvedImports: false,
|
|
70
|
+
runtimeLogLevel: argv['runtime-log-level'] || 0,
|
|
70
71
|
}, (0, executor_1.taskHandler)(block));
|
|
71
72
|
if (result.Error) {
|
|
72
73
|
throw new Error(result.Error);
|
|
73
74
|
}
|
|
75
|
+
for (const logs of result.Call.runtimeLogs) {
|
|
76
|
+
logger_1.defaultLogger.info(`RuntimeLogs:\n${logs}`);
|
|
77
|
+
}
|
|
74
78
|
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(block, result.Call.storageDiff, hash);
|
|
75
79
|
console.log(`Generated preview ${filePath}`);
|
|
76
80
|
if (argv['open']) {
|
|
@@ -85,9 +89,7 @@ const dryRunPreimage = async (argv) => {
|
|
|
85
89
|
if (outcome.isErr) {
|
|
86
90
|
throw new Error(outcome.asErr.toString());
|
|
87
91
|
}
|
|
88
|
-
|
|
89
|
-
logger_1.defaultLogger.info(outcome.toHuman(), 'dry_run_outcome');
|
|
90
|
-
}
|
|
92
|
+
logger_1.defaultLogger.info(outcome.toHuman(), 'dry_run_outcome');
|
|
91
93
|
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(context.chain.head, storageDiff, (0, util_crypto_1.blake2AsHex)(argv['extrinsic'], 256));
|
|
92
94
|
console.log(`Generated preview ${filePath}`);
|
|
93
95
|
if (argv['open']) {
|
package/lib/dry-run.js
CHANGED
|
@@ -14,9 +14,7 @@ const dryRun = async (argv) => {
|
|
|
14
14
|
if (outcome.isErr) {
|
|
15
15
|
throw new Error(outcome.asErr.toString());
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
logger_1.defaultLogger.info(outcome.toHuman(), 'dry_run_outcome');
|
|
19
|
-
}
|
|
17
|
+
logger_1.defaultLogger.info(outcome.toHuman(), 'dry_run_outcome');
|
|
20
18
|
if (argv['html']) {
|
|
21
19
|
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(context.chain.head, storageDiff, (0, util_crypto_1.blake2AsHex)(argv['extrinsic'], 256));
|
|
22
20
|
console.log(`Generated preview ${filePath}`);
|
package/lib/executor.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export declare const runTask: (task: {
|
|
|
30
30
|
storage: [HexString, HexString | null][];
|
|
31
31
|
mockSignatureHost: boolean;
|
|
32
32
|
allowUnresolvedImports: boolean;
|
|
33
|
+
runtimeLogLevel: number;
|
|
33
34
|
}, callback?: JsCallback) => Promise<any>;
|
|
34
35
|
export declare const taskHandler: (block: Block) => JsCallback;
|
|
35
36
|
export declare const emptyTaskHandler: {
|
package/lib/executor.js
CHANGED
package/lib/genesis-provider.js
CHANGED
package/lib/run-block.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runBlock = void 0;
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
|
+
const logger_1 = require("./logger");
|
|
5
6
|
const generate_html_diff_1 = require("./utils/generate-html-diff");
|
|
6
7
|
const open_html_1 = require("./utils/open-html");
|
|
7
8
|
const executor_1 = require("./executor");
|
|
8
9
|
const setup_1 = require("./setup");
|
|
9
10
|
const runBlock = async (argv) => {
|
|
10
|
-
const context = await (0, setup_1.setup)(argv);
|
|
11
|
+
const context = await (0, setup_1.setup)(argv, true);
|
|
11
12
|
const header = await context.chain.head.header;
|
|
12
13
|
const wasm = await context.chain.head.wasm;
|
|
13
14
|
const block = context.chain.head;
|
|
@@ -25,10 +26,14 @@ const runBlock = async (argv) => {
|
|
|
25
26
|
storage: [],
|
|
26
27
|
mockSignatureHost: false,
|
|
27
28
|
allowUnresolvedImports: false,
|
|
29
|
+
runtimeLogLevel: argv['runtime-log-level'] || 0,
|
|
28
30
|
}, (0, executor_1.taskHandler)(parent));
|
|
29
31
|
if (result.Error) {
|
|
30
32
|
throw new Error(result.Error);
|
|
31
33
|
}
|
|
34
|
+
for (const logs of result.Call.runtimeLogs) {
|
|
35
|
+
logger_1.defaultLogger.info(`RuntimeLogs:\n${logs}`);
|
|
36
|
+
}
|
|
32
37
|
if (argv['html']) {
|
|
33
38
|
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(parent, result.Call.storageDiff, block.hash);
|
|
34
39
|
console.log(`Generated preview ${filePath}`);
|
package/lib/schema/index.d.ts
CHANGED
|
@@ -64,7 +64,7 @@ export type Genesis = z.infer<typeof genesisSchema>;
|
|
|
64
64
|
export declare const configSchema: z.ZodObject<{
|
|
65
65
|
port: z.ZodOptional<z.ZodNumber>;
|
|
66
66
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
67
|
-
block: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
|
|
67
|
+
block: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodNull]>>;
|
|
68
68
|
'build-block-mode': z.ZodOptional<z.ZodNativeEnum<typeof BuildBlockMode>>;
|
|
69
69
|
'import-storage': z.ZodOptional<z.ZodAny>;
|
|
70
70
|
'mock-signature-host': z.ZodOptional<z.ZodBoolean>;
|
|
@@ -132,10 +132,16 @@ export declare const configSchema: z.ZodObject<{
|
|
|
132
132
|
}>]>>;
|
|
133
133
|
timestamp: z.ZodOptional<z.ZodNumber>;
|
|
134
134
|
'registered-types': z.ZodOptional<z.ZodAny>;
|
|
135
|
+
'runtime-log-level': z.ZodOptional<z.ZodNumber>;
|
|
135
136
|
}, "strict", z.ZodTypeAny, {
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
port?: number | undefined;
|
|
138
|
+
endpoint?: string | undefined;
|
|
139
|
+
block?: string | number | null | undefined;
|
|
140
|
+
'build-block-mode'?: BuildBlockMode | undefined;
|
|
141
|
+
'import-storage'?: any;
|
|
142
|
+
'mock-signature-host'?: boolean | undefined;
|
|
138
143
|
db?: string | undefined;
|
|
144
|
+
'wasm-override'?: string | undefined;
|
|
139
145
|
genesis?: string | {
|
|
140
146
|
name: string;
|
|
141
147
|
properties: {
|
|
@@ -150,17 +156,18 @@ export declare const configSchema: z.ZodObject<{
|
|
|
150
156
|
};
|
|
151
157
|
};
|
|
152
158
|
} | undefined;
|
|
159
|
+
timestamp?: number | undefined;
|
|
160
|
+
'registered-types'?: any;
|
|
161
|
+
'runtime-log-level'?: number | undefined;
|
|
162
|
+
}, {
|
|
153
163
|
port?: number | undefined;
|
|
154
164
|
endpoint?: string | undefined;
|
|
165
|
+
block?: string | number | null | undefined;
|
|
155
166
|
'build-block-mode'?: BuildBlockMode | undefined;
|
|
156
167
|
'import-storage'?: any;
|
|
157
168
|
'mock-signature-host'?: boolean | undefined;
|
|
158
|
-
'wasm-override'?: string | undefined;
|
|
159
|
-
'registered-types'?: any;
|
|
160
|
-
}, {
|
|
161
|
-
timestamp?: number | undefined;
|
|
162
|
-
block?: string | number | undefined;
|
|
163
169
|
db?: string | undefined;
|
|
170
|
+
'wasm-override'?: string | undefined;
|
|
164
171
|
genesis?: string | {
|
|
165
172
|
name: string;
|
|
166
173
|
properties: {
|
|
@@ -175,12 +182,8 @@ export declare const configSchema: z.ZodObject<{
|
|
|
175
182
|
};
|
|
176
183
|
};
|
|
177
184
|
} | undefined;
|
|
178
|
-
|
|
179
|
-
endpoint?: string | undefined;
|
|
180
|
-
'build-block-mode'?: BuildBlockMode | undefined;
|
|
181
|
-
'import-storage'?: any;
|
|
182
|
-
'mock-signature-host'?: boolean | undefined;
|
|
183
|
-
'wasm-override'?: string | undefined;
|
|
185
|
+
timestamp?: number | undefined;
|
|
184
186
|
'registered-types'?: any;
|
|
187
|
+
'runtime-log-level'?: number | undefined;
|
|
185
188
|
}>;
|
|
186
189
|
export type Config = z.infer<typeof configSchema>;
|
package/lib/schema/index.js
CHANGED
|
@@ -17,7 +17,7 @@ exports.configSchema = zod_1.z
|
|
|
17
17
|
.object({
|
|
18
18
|
port: zod_1.z.number().optional(),
|
|
19
19
|
endpoint: zod_1.z.string().optional(),
|
|
20
|
-
block: zod_1.z.union([zod_1.z.string().length(66).startsWith('0x'), zod_1.z.number()]).optional(),
|
|
20
|
+
block: zod_1.z.union([zod_1.z.string().length(66).startsWith('0x'), zod_1.z.number(), zod_1.z.null()]).optional(),
|
|
21
21
|
'build-block-mode': zod_1.z.nativeEnum(txpool_1.BuildBlockMode).optional(),
|
|
22
22
|
'import-storage': zod_1.z.any().optional(),
|
|
23
23
|
'mock-signature-host': zod_1.z.boolean().optional(),
|
|
@@ -26,5 +26,6 @@ exports.configSchema = zod_1.z
|
|
|
26
26
|
genesis: zod_1.z.union([zod_1.z.string(), exports.genesisSchema]).optional(),
|
|
27
27
|
timestamp: zod_1.z.number().optional(),
|
|
28
28
|
'registered-types': zod_1.z.any().optional(),
|
|
29
|
+
'runtime-log-level': zod_1.z.number().min(0).max(5).optional(),
|
|
29
30
|
})
|
|
30
31
|
.strict();
|
package/lib/server.js
CHANGED
|
@@ -50,7 +50,7 @@ const createWS = async (port) => {
|
|
|
50
50
|
const createServer = async (handler, port) => {
|
|
51
51
|
let wss;
|
|
52
52
|
let listenPort;
|
|
53
|
-
for (let i = 0; i <
|
|
53
|
+
for (let i = 0; i < 10; i++) {
|
|
54
54
|
const preferPort = (port ?? 0) > 0 ? (port ?? 0) + i : 0;
|
|
55
55
|
logger.debug('Try starting on port %d', preferPort);
|
|
56
56
|
const [maybeWss, maybeListenPort] = await createWS(preferPort);
|
|
@@ -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
|
|
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') {
|
|
@@ -62,14 +62,23 @@ const setup = async (argv) => {
|
|
|
62
62
|
},
|
|
63
63
|
mockSignatureHost: argv['mock-signature-host'],
|
|
64
64
|
allowUnresolvedImports: argv['allow-unresolved-imports'],
|
|
65
|
+
runtimeLogLevel: argv['runtime-log-level'],
|
|
65
66
|
registeredTypes: argv['registered-types'],
|
|
66
67
|
});
|
|
67
68
|
if (argv.timestamp)
|
|
68
69
|
await (0, time_travel_1.timeTravel)(chain, argv.timestamp);
|
|
70
|
+
let at;
|
|
71
|
+
if (runBlock) {
|
|
72
|
+
// in case of run block we need to apply wasm-override and import-storage to parent block
|
|
73
|
+
const block = await chain.head.parentBlock;
|
|
74
|
+
if (!block)
|
|
75
|
+
throw new Error('Cannot find parent block');
|
|
76
|
+
at = block.hash;
|
|
77
|
+
}
|
|
69
78
|
// override wasm before importing storage, in case new pallets have been
|
|
70
79
|
// 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']);
|
|
80
|
+
await (0, import_storage_1.overrideWasm)(chain, argv['wasm-override'], at);
|
|
81
|
+
await (0, import_storage_1.importStorage)(chain, argv['import-storage'], at);
|
|
73
82
|
return { chain, api, ws: provider };
|
|
74
83
|
};
|
|
75
84
|
exports.setup = setup;
|
|
@@ -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
|
-
|
|
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,50 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acala-network/chopsticks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
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": "
|
|
9
|
+
"build": "tsc -p ./tsconfig.json",
|
|
10
10
|
"script:start": "cd ../..; ts-node --transpile-only packages/chopsticks/src/cli.ts",
|
|
11
|
-
"script:run": "LOG_LEVEL=trace ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config
|
|
12
|
-
"dev:karura": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config
|
|
13
|
-
"dev:acala": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config
|
|
14
|
-
"dev:moonriver": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config
|
|
15
|
-
"dev:moonbeam": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config
|
|
11
|
+
"script:run": "cd ../..; LOG_LEVEL=trace ts-node-dev --transpile-only --inspect --notify=false packages/chopsticks/src/cli.ts -- dev --config=configs/dev.yml",
|
|
12
|
+
"dev:karura": "cd ../..; ts-node-dev --transpile-only --inspect --notify=false packages/chopsticks/src/cli.ts -- dev --config=configs/karura.yml",
|
|
13
|
+
"dev:acala": "cd ../..; ts-node-dev --transpile-only --inspect --notify=false packages/chopsticks/src/cli.ts -- dev --config=configs/acala.yml",
|
|
14
|
+
"dev:moonriver": "cd ../..; ts-node-dev --transpile-only --inspect --notify=false packages/chopsticks/src/cli.ts -- dev --config=configs/moonriver.yml",
|
|
15
|
+
"dev:moonbeam": "cd ../..; ts-node-dev --transpile-only --inspect --notify=false packages/chopsticks/src/cli.ts -- dev --config=configs/moonbeam.yml"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@acala-network/chopsticks-executor": "0.
|
|
19
|
-
"@polkadot/api": "^
|
|
20
|
-
"@polkadot/rpc-provider": "^
|
|
21
|
-
"@polkadot/types": "^
|
|
22
|
-
"@polkadot/types-codec": "^
|
|
23
|
-
"@polkadot/types-known": "^
|
|
24
|
-
"@polkadot/util": "^
|
|
25
|
-
"@polkadot/util-crypto": "^
|
|
26
|
-
"axios": "^1.3.
|
|
18
|
+
"@acala-network/chopsticks-executor": "0.6.0",
|
|
19
|
+
"@polkadot/api": "^10.2.1",
|
|
20
|
+
"@polkadot/rpc-provider": "^10.2.1",
|
|
21
|
+
"@polkadot/types": "^10.2.1",
|
|
22
|
+
"@polkadot/types-codec": "^10.2.1",
|
|
23
|
+
"@polkadot/types-known": "^10.2.1",
|
|
24
|
+
"@polkadot/util": "^11.1.2",
|
|
25
|
+
"@polkadot/util-crypto": "^11.1.2",
|
|
26
|
+
"axios": "^1.3.4",
|
|
27
27
|
"js-yaml": "^4.1.0",
|
|
28
28
|
"jsondiffpatch": "^0.4.1",
|
|
29
29
|
"lodash": "^4.17.21",
|
|
30
30
|
"pino": "^8.11.0",
|
|
31
|
-
"pino-pretty": "^
|
|
31
|
+
"pino-pretty": "^10.0.0",
|
|
32
32
|
"reflect-metadata": "^0.1.13",
|
|
33
|
-
"sqlite3": "^5.1.
|
|
33
|
+
"sqlite3": "^5.1.6",
|
|
34
34
|
"typeorm": "^0.3.12",
|
|
35
|
-
"ws": "^8.
|
|
35
|
+
"ws": "^8.13.0",
|
|
36
36
|
"yargs": "^17.7.1",
|
|
37
|
-
"zod": "^3.
|
|
37
|
+
"zod": "^3.21.4"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/js-yaml": "^4.0.5",
|
|
41
|
-
"@types/lodash": "^4.14.
|
|
42
|
-
"@types/node": "^18.
|
|
41
|
+
"@types/lodash": "^4.14.192",
|
|
42
|
+
"@types/node": "^18.15.10",
|
|
43
43
|
"@types/ws": "^8.5.4",
|
|
44
|
-
"@types/yargs": "^17.0.
|
|
44
|
+
"@types/yargs": "^17.0.24",
|
|
45
45
|
"ts-node": "^10.9.1",
|
|
46
46
|
"ts-node-dev": "^2.0.0",
|
|
47
|
-
"typescript": "^
|
|
47
|
+
"typescript": "^5.0.2"
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
50
|
"lib",
|